🔥 Cleaning up

This commit is contained in:
Hampus Kraft
2020-03-19 08:12:00 +01:00
parent 485ad466f3
commit 0d8a4ee9fa
18 changed files with 94 additions and 56 deletions

View File

@@ -1,3 +1,3 @@
examples
node_modules
npm-debug.log
npm-debug.log

View File

@@ -8,4 +8,4 @@ indent_size = 2
end_of_line = lf
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
trim_trailing_whitespace = true

2
.gitignore vendored
View File

@@ -3,7 +3,7 @@ dist
*.log
hasura
config.yaml
private.pem
node_modules
yarn-error.log
package-lock.json
private.pem

View File

@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@@ -121,4 +121,4 @@ insert into public.roles (role)
values ('anonymous');
insert into auth.auth_providers (provider)
values ('github'), ('facebook'), ('twitter'), ('google');
values ('github'), ('facebook'), ('twitter'), ('google');

View File

@@ -33,6 +33,7 @@
"helmet": "3.21.3",
"hibp": "8.0.0",
"jose": "1.25.0",
"nodemailer": "6.4.5",
"otplib": "12.0.1",
"qrcode": "1.4.4",
"tsconfig-paths": "3.9.0",
@@ -49,6 +50,7 @@
"@types/jest": "25.1.4",
"@types/jsonwebtoken": "8.3.8",
"@types/node": "13.9.1",
"@types/nodemailer": "6.4.0",
"@types/qrcode": "1.3.4",
"@types/supertest": "2.0.8",
"@types/uuid": "7.0.2",

View File

@@ -13,8 +13,7 @@ async function disable({ headers, body }: Request, res: Response): Promise<unkno
const { code } = await mfaSchema.validateAsync(body)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const decodedToken = verify(headers.authorization!)
const decodedToken = verify(headers.authorization)
const user_id = decodedToken['https://hasura.io/jwt/claims']['x-hasura-user-id']
try {

View File

@@ -13,8 +13,7 @@ async function enable({ headers, body }: Request, res: Response): Promise<unknow
const { code } = await mfaSchema.validateAsync(body)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const decodedToken = verify(headers.authorization!)
const decodedToken = verify(headers.authorization)
const user_id = decodedToken['https://hasura.io/jwt/claims']['x-hasura-user-id']
try {

View File

@@ -10,8 +10,7 @@ import { verify } from '@shared/jwt'
async function generate({ headers }: Request, res: Response): Promise<unknown> {
let image_url: string
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const decodedToken = verify(headers.authorization!)
const decodedToken = verify(headers.authorization)
const user_id = decodedToken['https://hasura.io/jwt/claims']['x-hasura-user-id']
const { OTP_ISSUER = 'HBP' } = process.env

View File

@@ -7,6 +7,7 @@ import { insertUser } from '@shared/queries'
import { pwnedPassword } from 'hibp'
import { registerSchema } from '@shared/schema'
import { request } from '@shared/request'
// import { sendEmail } from '@shared/email'
import { v4 as uuidv4 } from 'uuid'
async function register({ body }: Request, res: Response): Promise<unknown> {
@@ -30,13 +31,15 @@ async function register({ body }: Request, res: Response): Promise<unknown> {
throw Boom.badImplementation()
}
const ticket = uuidv4()
try {
await request(insertUser, {
user: {
email,
active,
ticket,
username,
ticket: uuidv4(),
user_accounts: {
data: {
email,
@@ -46,6 +49,14 @@ async function register({ body }: Request, res: Response): Promise<unknown> {
}
}
})
/*if (!active) {
await sendEmail({
to: email,
subject: 'Hello World',
text: `Ticket: ${ticket}`
})
}*/
} catch (err) {
throw Boom.badImplementation()
}

View File

@@ -7,8 +7,7 @@ import { request } from '@shared/request'
import { verify } from '@shared/jwt'
async function revoke({ headers }: Request, res: Response): Promise<unknown> {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const decodedToken = verify(headers.authorization!)
const decodedToken = verify(headers.authorization)
const user_id = decodedToken['https://hasura.io/jwt/claims']['x-hasura-user-id']
try {

View File

@@ -6,17 +6,33 @@ import { deleteUserById } from '@shared/queries'
import { request } from '@shared/request'
import { verify } from '@shared/jwt'
interface HasuraData {
delete_private_user_accounts: { affected_rows: number }
delete_private_refresh_tokens: { affected_rows: number }
delete_users: { affected_rows: number }
}
async function remove({ headers }: Request, res: Response): Promise<unknown> {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const decodedToken = verify(headers.authorization!)
let hasuraData: HasuraData
const decodedToken = verify(headers.authorization)
const user_id = decodedToken['https://hasura.io/jwt/claims']['x-hasura-user-id']
try {
await request(deleteUserById, { user_id })
hasuraData = (await request(deleteUserById, { user_id })) as HasuraData
} catch (err) {
throw Boom.badImplementation()
}
const deleteUsers = hasuraData.delete_users
const deleteAccounts = hasuraData.delete_private_user_accounts
const doesNotExist = !deleteAccounts.affected_rows || !deleteUsers.affected_rows
if (doesNotExist) {
throw Boom.unauthorized('Invalid or expired JWT token.')
}
return res.status(204).send()
}

View File

@@ -7,7 +7,7 @@ import { storagePermission } from './rules'
import { verify } from '@shared/jwt'
async function delete_file(req: Request, res: Response): Promise<unknown> {
const key = `${req.params[0]}`
const key = req.params[0]
// check storage rules if allowed to get meta info of file
const jwt_token = verify(req.headers.authorization)
@@ -25,9 +25,7 @@ async function delete_file(req: Request, res: Response): Promise<unknown> {
try {
await s3.deleteObject(params).promise()
} catch (e) {
console.error('error')
console.error({ e })
} catch (err) {
throw Boom.badImplementation()
}

View File

@@ -5,7 +5,7 @@ import { asyncWrapper } from '@shared/helpers'
import { s3 } from '@shared/s3'
async function get_file(req: Request, res: Response): Promise<void> {
const key = `${req.params[0]}`
const key = req.params[0]
const token = req.query.token
// get file info
@@ -18,10 +18,8 @@ async function get_file(req: Request, res: Response): Promise<void> {
try {
data = await s3.headObject(params).promise()
} catch (e) {
if (e) {
throw Boom.notFound()
}
} catch (err) {
throw Boom.notFound()
}
if (!data?.Metadata) {
@@ -35,7 +33,7 @@ async function get_file(req: Request, res: Response): Promise<void> {
const stream = s3.getObject(params).createReadStream()
// forward errors
stream.on('error', function error(err) {
stream.on('error', err => {
console.error(err)
throw Boom.badImplementation()
})

View File

@@ -7,7 +7,7 @@ import { storagePermission } from './rules'
import { verify } from '@shared/jwt'
async function get_file(req: Request, res: Response): Promise<unknown> {
const key = `${req.params[0]}`
const key = req.params[0]
// check storage rules if allowed to get meta info of file
const jwt_token = verify(req.headers.authorization)
@@ -26,9 +26,7 @@ async function get_file(req: Request, res: Response): Promise<unknown> {
let data
try {
data = await s3.headObject(params).promise()
} catch (e) {
console.error('error')
console.error({ e })
} catch (err) {
throw Boom.badImplementation()
}

View File

@@ -1,34 +1,13 @@
import { Request, Response } from 'express'
import Boom from '@hapi/boom'
import { UploadedFile } from 'express-fileupload'
import { asyncWrapper } from '@shared/helpers'
import { s3 } from '@shared/s3'
import { storagePermission } from './rules'
import { v4 as uuidv4 } from 'uuid'
import { verify } from '@shared/jwt'
interface UploadedFile {
/** file name */
name: string
/** A function to move the file elsewhere on your server */
mv(path: string, callback: (err: unknown) => void): void
mv(path: string): Promise<void>
/** Encoding type of the file */
encoding: string
/** The mimetype of your file */
mimetype: string
/** A buffer representation of your file, returns empty buffer in case useTempFiles option was set to true. */
data: Buffer
/** A path to the temporary file in case useTempFiles option was set to true. */
tempFilePath: string
/** A boolean that represents if the file is over the size limit */
truncated: boolean
/** Uploaded size in bytes */
size: number
/** MD5 checksum of the uploaded file */
md5: string
}
async function upload_file(req: Request, res: Response): Promise<unknown> {
if (!req.files?.file) {
throw Boom.badRequest('No file')
@@ -65,9 +44,7 @@ async function upload_file(req: Request, res: Response): Promise<unknown> {
try {
await s3.upload(upload_params).promise()
} catch (e) {
console.log('error')
console.log({ e })
} catch (err) {
throw Boom.badImplementation()
}

30
src/shared/email.ts Normal file
View File

@@ -0,0 +1,30 @@
import nodemailer from 'nodemailer'
interface Email {
to: string
text: string
from?: string
subject: string
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function sendEmail(options: Email): Promise<any> {
const { to, text, from = '"noreply" <noreply@example.com>', subject } = options
const testAccount = await nodemailer.createTestAccount()
const transporter = nodemailer.createTransport({
host: 'smtp.ethereal.email',
port: 587,
secure: false,
auth: {
user: testAccount.user,
pass: testAccount.pass
}
})
const info = await transporter.sendMail({ from, to, subject, text })
console.log('Message sent: %s', info.messageId)
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info))
}

View File

@@ -583,6 +583,13 @@
version "13.9.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.1.tgz#96f606f8cd67fb018847d9b61e93997dabdefc72"
"@types/nodemailer@6.4.0":
version "6.4.0"
resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.0.tgz#d8c039be3ed685c4719a026455555be82c124b74"
integrity sha512-KY7bFWB0MahRZvVW4CuW83qcCDny59pJJ0MQ5ifvfcjNwPlIT0vW4uARO4u1gtkYnWdhSvURegecY/tzcukJcA==
dependencies:
"@types/node" "*"
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
@@ -3718,6 +3725,11 @@ node-pre-gyp@^0.14.0:
semver "^5.3.0"
tar "^4.4.2"
nodemailer@6.4.5:
version "6.4.5"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.4.5.tgz#45614c6454d1a947242105eeddae03df87e29916"
integrity sha512-NH7aNVQyZLAvGr2+EOto7znvz+qJ02Cb/xpou98ApUt5tEAUSVUxhvHvgV/8I5dhjKTYqUw0nasoKzLNBJKrDQ==
nopt@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"