Compare commits
30 commits
main
...
renovate/s
Author | SHA1 | Date | |
---|---|---|---|
c515f8e871 | |||
c9c972cd17 | |||
44b6f40270 | |||
8f33e77ee2 | |||
7e4fbb5685 | |||
5b5569184f | |||
90aeca84d0 | |||
e104a864f9 | |||
759a03a56c | |||
31e1572f03 | |||
9868a8d8cd | |||
14d8461a8b | |||
2e0e53043c | |||
e0a9db71a7 | |||
60ca7e666a | |||
12bb6aba90 | |||
4621a82693 | |||
0a1ae819b6 | |||
460b483299 | |||
60303c8c82 | |||
30885dd00a | |||
410c58cc7f | |||
2802ed0c4f | |||
571adcc8aa | |||
fa94bbf7f4 | |||
4928ba991c | |||
a26f8bf775 | |||
06f786e421 | |||
7b40a0efae | |||
994bc2ef4c |
11 changed files with 1531 additions and 617 deletions
|
@ -1,25 +0,0 @@
|
||||||
export DEBUG="hostr*"
|
|
||||||
|
|
||||||
export NODE_ENV=development
|
|
||||||
export PORT=4040
|
|
||||||
export WEB_BASE_URL=http://localhost:$PORT
|
|
||||||
export API_BASE_URL=$WEB_BASE_URL/api
|
|
||||||
export UPLOAD_STORAGE_PATH=$HOME/.hostr/uploads
|
|
||||||
export COOKIE_KEY=INSECURE
|
|
||||||
export EMAIL_FROM=
|
|
||||||
export EMAIL_NAME=
|
|
||||||
|
|
||||||
export STATSD_HOST=localhost
|
|
||||||
export DATABASE_URL=postgresql://hostr:hostr@database:5432/hostr
|
|
||||||
export REDIS_URL=redis://localhost:6379
|
|
||||||
export SENDGRID_KEY=
|
|
||||||
export STRIPE_SECRET_KEY=
|
|
||||||
export STRIPE_PUBLIC_KEY=
|
|
||||||
|
|
||||||
# optional, some functionality will be disabled
|
|
||||||
export AWS_ENDPOINT= # only for AWS-like providers, not AWS
|
|
||||||
export AWS_ACCESS_KEY_ID=
|
|
||||||
export AWS_SECRET_ACCESS_KEY=
|
|
||||||
export AWS_BUCKET=
|
|
||||||
export VIRUSTOTAL_KEY=
|
|
||||||
export SENTRY_DSN=
|
|
|
@ -1,12 +0,0 @@
|
||||||
WEB_BASE_URL=http://localhost:3000
|
|
||||||
API_BASE_URL=http://localhost:3000/api
|
|
||||||
UPLOAD_STORAGE_PATH=/hostr/uploads
|
|
||||||
COOKIE_KEY=TESTING
|
|
||||||
EMAIL_FROM=jonathan@hostr.co
|
|
||||||
EMAIL_NAME="Jonathan from Hostr"
|
|
||||||
DATABASE_URL=postgresql://hostr:hostr@database:5432/hostr
|
|
||||||
REDIS_URL=redis://redis:6379
|
|
||||||
AWS_ENDPOINT=http://minio:9000
|
|
||||||
AWS_ACCESS_KEY_ID=7HYV3KPRGQ8Z5YCDNWC6
|
|
||||||
AWS_SECRET_ACCESS_KEY=0kWP/ZkgIwQzgL9t4SGv9Uc93rO//OdyqMH329b/
|
|
||||||
AWS_BUCKET=hostr
|
|
41
.forgejo/workflows/build-image.yml
Normal file
41
.forgejo/workflows/build-image.yml
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: main
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-image:
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- name: Set current date as env variable
|
||||||
|
run: echo "NOW=$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_ENV
|
||||||
|
- name: Fix for bad os check
|
||||||
|
run: echo "RUNNER_OS=Linux" >> $GITHUB_ENV
|
||||||
|
- name: Login to Forgejo Registry
|
||||||
|
uses: https://cremin.dev/actions/podman-login@v1
|
||||||
|
with:
|
||||||
|
registry: cremin.dev
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
||||||
|
- name: Check out repository
|
||||||
|
uses: https://cremin.dev/actions/checkout@v4
|
||||||
|
- name: Build image
|
||||||
|
uses: https://cremin.dev/actions/buildah-build@v2
|
||||||
|
with:
|
||||||
|
containerfiles: ./Containerfile
|
||||||
|
context: ./
|
||||||
|
oci: true
|
||||||
|
layers: true
|
||||||
|
image: hostr
|
||||||
|
tags: latest ${{ github.sha }}
|
||||||
|
- name: Push image
|
||||||
|
uses: https://cremin.dev/actions/push-to-registry@v2
|
||||||
|
with:
|
||||||
|
registry: cremin.dev/jonathan
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
||||||
|
image: hostr
|
||||||
|
tags: latest ${{ github.sha }}
|
|
@ -1,57 +0,0 @@
|
||||||
name: ci
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-image:
|
|
||||||
runs-on: self-hosted
|
|
||||||
steps:
|
|
||||||
- name: Set current date as env variable
|
|
||||||
run: echo "NOW=$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_ENV
|
|
||||||
- name: Fix for bad os check
|
|
||||||
run: echo "RUNNER_OS=Linux" >> $GITHUB_ENV
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: https://cremin.dev/actions/docker-login@v3
|
|
||||||
with:
|
|
||||||
registry: cremin.dev
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
|
||||||
- name: Check out repository
|
|
||||||
uses: https://cremin.dev/actions/checkout@v4
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: https://cremin.dev/actions/docker-setup-buildx@v3
|
|
||||||
- name: Build and push
|
|
||||||
uses: https://cremin.dev/actions/docker-build-push@v6
|
|
||||||
with:
|
|
||||||
file: ./Containerfile
|
|
||||||
context: ./
|
|
||||||
tags: cremin.dev/jonathan/hostr:latest,cremin.dev/jonathan/hostr:${{ github.sha }}
|
|
||||||
push: true
|
|
||||||
test-image:
|
|
||||||
runs-on: node22
|
|
||||||
needs: build-image
|
|
||||||
services:
|
|
||||||
database:
|
|
||||||
image: postgres:14-alpine
|
|
||||||
env:
|
|
||||||
POSTGRES_PASSWORD: hostr
|
|
||||||
POSTGRES_USER: hostr
|
|
||||||
POSTGRES_DB: hostr
|
|
||||||
redis:
|
|
||||||
image: redis:4.0.2-alpine
|
|
||||||
minio:
|
|
||||||
image: minio/minio
|
|
||||||
env:
|
|
||||||
MINIO_ACCESS_KEY: 7HYV3KPRGQ8Z5YCDNWC6
|
|
||||||
MINIO_SECRET_KEY: 0kWP/ZkgIwQzgL9t4SGv9Uc93rO//OdyqMH329b/
|
|
||||||
cmd: ["server", "/export"]
|
|
||||||
steps:
|
|
||||||
- name: Check out repository
|
|
||||||
uses: https://cremin.dev/actions/checkout@v4
|
|
||||||
- name: Test image
|
|
||||||
run: |
|
|
||||||
docker run --env-file ./.forgejo/workflows/.env --rm -it cremin.dev/jonathan/hostr:${{ github.sha }} yarn test
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
||||||
.envrc
|
.env*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
node_modules
|
node_modules
|
||||||
|
@ -7,7 +7,6 @@ jspm_packages
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
web/public/build
|
web/public/build
|
||||||
web/public/styles/*.css
|
web/public/styles/*.css
|
||||||
web/public/styles/*.css.map
|
|
||||||
*.gz
|
*.gz
|
||||||
minigun*.json
|
minigun*.json
|
||||||
test*.json
|
test*.json
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM node:22.16
|
FROM node:16.13.1
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
22
Makefile
22
Makefile
|
@ -10,36 +10,36 @@ help:
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: ## Run `yarn run build`
|
build: ## Run `yarn run build`
|
||||||
podman compose run --rm app yarn run build
|
docker-compose run --rm app yarn run build
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: ## Run tests
|
test: ## Run tests
|
||||||
podman compose run --rm app yarn test
|
docker-compose run --rm app yarn test
|
||||||
|
|
||||||
.PHONY: logs
|
.PHONY: logs
|
||||||
logs: ## Tail the app and worker logs
|
logs: ## Tail the app and worker logs
|
||||||
podman compose logs -f app worker
|
docker-compose logs -f app worker
|
||||||
|
|
||||||
.PHONY: migrate
|
.PHONY: migrate
|
||||||
migrate: ## Migrate database schema
|
migrate: ## Migrate database schema
|
||||||
podman compose run --rm app yarn run initdb
|
docker-compose run --rm app yarn run initdb
|
||||||
|
|
||||||
.PHONY: init
|
.PHONY: init
|
||||||
init: ## Migrate database schema
|
init: ## Migrate database schema
|
||||||
podman compose run --rm app yarn run init
|
docker-compose run --rm app yarn run init
|
||||||
|
|
||||||
.PHONY: watch-frontend
|
.PHONY: watch-frontend
|
||||||
watch-frontend: ## Build and watch for changes
|
watch-frontend: ## Build and watch for changes
|
||||||
podman compose run --rm app yarn run watch
|
docker-compose run --rm app yarn run watch
|
||||||
|
|
||||||
.PHONY: podman compose-up
|
.PHONY: docker-compose-up
|
||||||
podman compose-up: ## Start (and create) docker containers
|
docker-compose-up: ## Start (and create) docker containers
|
||||||
podman compose up -d
|
docker-compose up -d
|
||||||
|
|
||||||
.PHONY: yarn
|
.PHONY: yarn
|
||||||
yarn: ## Update yarn dependencies
|
yarn: ## Update yarn dependencies
|
||||||
podman compose run --rm app yarn
|
docker-compose run --rm app yarn
|
||||||
|
|
||||||
.PHONY: shell
|
.PHONY: shell
|
||||||
shell: ## Run shell
|
shell: ## Run shell
|
||||||
podman compose run --rm app sh
|
docker-compose run --rm app sh
|
||||||
|
|
|
@ -61,7 +61,7 @@ services:
|
||||||
- "3001:3000"
|
- "3001:3000"
|
||||||
command: yarn run worker
|
command: yarn run worker
|
||||||
database:
|
database:
|
||||||
image: "postgres:14-alpine"
|
image: "postgres:10-alpine"
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "5432:5432"
|
||||||
environment:
|
environment:
|
||||||
|
@ -69,7 +69,7 @@ services:
|
||||||
POSTGRES_USER: "hostr"
|
POSTGRES_USER: "hostr"
|
||||||
POSTGRES_DB: "hostr"
|
POSTGRES_DB: "hostr"
|
||||||
redis:
|
redis:
|
||||||
image: "redis:8-alpine"
|
image: "redis:4.0.14-alpine"
|
||||||
ports:
|
ports:
|
||||||
- "6379:6379"
|
- "6379:6379"
|
||||||
minio:
|
minio:
|
||||||
|
|
16
package.json
16
package.json
|
@ -5,14 +5,14 @@
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.0.0"
|
"node": ">=11.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn run build-js && yarn run build-sass",
|
"build": "yarn run build-js && yarn run build-sass",
|
||||||
"build-js": "NODE_OPTIONS=--openssl-legacy-provider webpack --progress -p -c webpack.config.js",
|
"build-js": "webpack --progress -p -c webpack.config.js",
|
||||||
"build-sass": "sass --load-path=./node_modules/ web/public/styles/",
|
"build-sass": "node-sass --include-path ./node_modules/ -r -o web/public/styles/ web/public/styles/",
|
||||||
"heroku-postbuild": "yarn run build",
|
"heroku-postbuild": "yarn run build",
|
||||||
"init": "node -e \"require('./lib/storage').default();\"",
|
"init": "babel-node -e \"require('./lib/storage').default();\"",
|
||||||
"initdb": "node -r babel-register test/initdb.js",
|
"initdb": "node -r babel-register test/initdb.js",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"start": "node -r babel-register app.js",
|
"start": "node -r babel-register app.js",
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
"watch": "concurrently -k -n watch-js,watch-sass \"yarn run watch-js\" \"yarn run watch-sass\"",
|
"watch": "concurrently -k -n watch-js,watch-sass \"yarn run watch-js\" \"yarn run watch-sass\"",
|
||||||
"watch-js": "webpack -w --mode=development --progress -c webpack.config.js",
|
"watch-js": "webpack -w --mode=development --progress -c webpack.config.js",
|
||||||
"watch-server": "nodemon -r babel-register -i web/public",
|
"watch-server": "nodemon -r babel-register -i web/public",
|
||||||
"watch-sass": "sass --load-path=./node_modules/ -w web/public/styles/"
|
"watch-sass": "node-sass --include-path ./node_modules/ -w -r -o web/public/styles/ web/public/styles/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sendgrid/mail": "^7.1.1",
|
"@sendgrid/mail": "^7.1.1",
|
||||||
|
@ -75,12 +75,11 @@
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"mz": "^2.7.0",
|
"mz": "^2.7.0",
|
||||||
"node-fetch": "^2.3.0",
|
"node-fetch": "^2.3.0",
|
||||||
|
"node-sass": "^7.0.0",
|
||||||
"node-uuid": "^1.4.8",
|
"node-uuid": "^1.4.8",
|
||||||
"nodemon": "^3.1.10",
|
|
||||||
"passwords": "^1.3.1",
|
"passwords": "^1.3.1",
|
||||||
"pg": "^8.0.3",
|
"pg": "^8.0.3",
|
||||||
"redis": "^3.0.2",
|
"redis": "^3.0.2",
|
||||||
"sass": "^1.89.2",
|
|
||||||
"sequelize": "^5.21.11",
|
"sequelize": "^5.21.11",
|
||||||
"smooth-scroll": "https://github.com/cferdinandi/smooth-scroll#5.3.7",
|
"smooth-scroll": "https://github.com/cferdinandi/smooth-scroll#5.3.7",
|
||||||
"statsy": "~0.2.0",
|
"statsy": "~0.2.0",
|
||||||
|
@ -96,7 +95,8 @@
|
||||||
"eslint-config-airbnb": "^18.1.0",
|
"eslint-config-airbnb": "^18.1.0",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.20.2",
|
||||||
"mocha": "^8.0.0",
|
"mocha": "^8.0.0",
|
||||||
|
"nodemon": "^2.0.2",
|
||||||
"supertest": "^4.0.2",
|
"supertest": "^4.0.2",
|
||||||
"tmp": "0.2.1"
|
"tmp": "0.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
115
web/lib/auth.js
115
web/lib/auth.js
|
@ -1,29 +1,29 @@
|
||||||
import crypto from "crypto";
|
import crypto from 'crypto';
|
||||||
import { join } from "path";
|
import { join } from 'path';
|
||||||
import passwords from "passwords";
|
import passwords from 'passwords';
|
||||||
import uuid from "node-uuid";
|
import uuid from 'node-uuid';
|
||||||
import views from "co-views";
|
import views from 'co-views';
|
||||||
import debugname from "debug";
|
import debugname from 'debug';
|
||||||
import sendgrid from "@sendgrid/mail";
|
import sendgrid from '@sendgrid/mail';
|
||||||
import models from "../../models";
|
import models from '../../models';
|
||||||
|
|
||||||
const render = views(join(__dirname, "..", "views"), { default: "ejs" });
|
const render = views(join(__dirname, '..', 'views'), { default: 'ejs' });
|
||||||
const debug = debugname("hostr-web:auth");
|
const debug = debugname('hostr-web:auth');
|
||||||
sendgrid.setApiKey(process.env.SENDGRID_KEY);
|
sendgrid.setApiKey(process.env.SENDGRID_KEY);
|
||||||
|
|
||||||
const from = process.env.EMAIL_FROM;
|
const from = process.env.EMAIL_FROM;
|
||||||
const fromname = process.env.EMAIL_NAME;
|
const fromname = process.env.EMAIL_NAME;
|
||||||
|
|
||||||
export async function authenticate(email, password) {
|
export async function authenticate(email, password) {
|
||||||
const remoteIp = this.headers["x-forwarded-for"] || this.ip;
|
const remoteIp = this.headers['x-forwarded-for'] || this.ip;
|
||||||
|
|
||||||
if (!password || password.length < 6) {
|
if (!password || password.length < 6) {
|
||||||
debug("No password, or password too short");
|
debug('No password, or password too short');
|
||||||
return new Error("Invalid login details");
|
return new Error('Invalid login details');
|
||||||
}
|
}
|
||||||
const count = await models.login.count({
|
const count = await models.login.count({
|
||||||
where: {
|
where: {
|
||||||
ip: remoteIp.split(",")[0],
|
ip: remoteIp.split(',')[0],
|
||||||
successful: false,
|
successful: false,
|
||||||
createdAt: {
|
createdAt: {
|
||||||
$gt: Math.ceil(Date.now()) - 600000,
|
$gt: Math.ceil(Date.now()) - 600000,
|
||||||
|
@ -32,8 +32,8 @@ export async function authenticate(email, password) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (count > 25) {
|
if (count > 25) {
|
||||||
debug("Throttling brute force");
|
debug('Throttling brute force');
|
||||||
return new Error("Invalid login details");
|
return new Error('Invalid login details');
|
||||||
}
|
}
|
||||||
const user = await models.user.findOne({
|
const user = await models.user.findOne({
|
||||||
where: {
|
where: {
|
||||||
|
@ -43,29 +43,30 @@ export async function authenticate(email, password) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const login = await models.login.create({
|
const login = await models.login.create({
|
||||||
ip: remoteIp.split(",")[0],
|
ip: remoteIp.split(',')[0],
|
||||||
successful: false,
|
successful: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (user && user.password) {
|
if (user && user.password) {
|
||||||
login.userId = user.id;
|
login.userId = user.id;
|
||||||
if (await passwords.verify(password, user.password)) {
|
if (await passwords.verify(password, user.password)) {
|
||||||
debug("Password verified");
|
debug('Password verified');
|
||||||
login.successful = true;
|
login.successful = true;
|
||||||
await login.save();
|
await login.save();
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
debug("Password invalid");
|
debug('Password invalid');
|
||||||
}
|
}
|
||||||
await login.save();
|
await login.save();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setupSession(user) {
|
|
||||||
debug("Setting up session");
|
|
||||||
const token = uuid.v4();
|
|
||||||
|
|
||||||
await this.redis.set(token, user.id, "EX", 604800);
|
export async function setupSession(user) {
|
||||||
|
debug('Setting up session');
|
||||||
|
const token = uuid.v4();
|
||||||
|
debug(user)
|
||||||
|
await this.redis.set(token, user.id, 'EX', 604800);
|
||||||
|
|
||||||
const sessionUser = {
|
const sessionUser = {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
|
@ -75,26 +76,27 @@ export async function setupSession(user) {
|
||||||
joined: user.createdAt,
|
joined: user.createdAt,
|
||||||
plan: user.plan,
|
plan: user.plan,
|
||||||
uploadsToday: await models.file.count({ userId: user.id }),
|
uploadsToday: await models.file.count({ userId: user.id }),
|
||||||
md5: crypto.createHash("md5").update(user.email).digest("hex"),
|
md5: crypto.createHash('md5').update(user.email).digest('hex'),
|
||||||
token,
|
token,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sessionUser.plan === "Pro") {
|
if (sessionUser.plan === 'Pro') {
|
||||||
sessionUser.maxFileSize = 524288000;
|
sessionUser.maxFileSize = 524288000;
|
||||||
sessionUser.dailyUploadAllowance = "unlimited";
|
sessionUser.dailyUploadAllowance = 'unlimited';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.session.user = sessionUser;
|
this.session.user = sessionUser;
|
||||||
if (this.request.body.remember && this.request.body.remember === "on") {
|
if (this.request.body.remember && this.request.body.remember === 'on') {
|
||||||
const remember = await models.remember.create({
|
const remember = await models.remember.create({
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
});
|
});
|
||||||
this.cookies.set("r", remember.id, { maxAge: 1209600000, httpOnly: true });
|
this.cookies.set('r', remember.id, { maxAge: 1209600000, httpOnly: true });
|
||||||
}
|
}
|
||||||
debug("Session set up");
|
debug('Session set up');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function signup(email, password, ip) {
|
export async function signup(email, password, ip) {
|
||||||
const existingUser = await models.user.findOne({
|
const existingUser = await models.user.findOne({
|
||||||
where: {
|
where: {
|
||||||
|
@ -103,29 +105,26 @@ export async function signup(email, password, ip) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (existingUser) {
|
if (existingUser) {
|
||||||
debug("Email already in use.");
|
debug('Email already in use.');
|
||||||
throw new Error("Email already in use.");
|
throw new Error('Email already in use.');
|
||||||
}
|
}
|
||||||
const cryptedPassword = await passwords.crypt(password);
|
const cryptedPassword = await passwords.crypt(password);
|
||||||
const user = await models.user.create(
|
const user = await models.user.create({
|
||||||
{
|
email,
|
||||||
|
password: cryptedPassword,
|
||||||
|
ip,
|
||||||
|
plan: 'Free',
|
||||||
|
activation: {
|
||||||
|
id: uuid(),
|
||||||
email,
|
email,
|
||||||
password: cryptedPassword,
|
|
||||||
ip,
|
|
||||||
plan: "Free",
|
|
||||||
activation: {
|
|
||||||
id: uuid(),
|
|
||||||
email,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
}, {
|
||||||
include: [models.activation],
|
include: [models.activation],
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
await user.save();
|
await user.save();
|
||||||
|
|
||||||
const html = await render("email/inlined/activate", {
|
const html = await render('email/inlined/activate', {
|
||||||
activationUrl: `${process.env.WEB_BASE_URL}/activate/${user.activation.id}`,
|
activationUrl: `${process.env.WEB_BASE_URL}/activate/${user.activation.id}`,
|
||||||
});
|
});
|
||||||
const text = `Thanks for signing up to Hostr!
|
const text = `Thanks for signing up to Hostr!
|
||||||
|
@ -137,15 +136,18 @@ ${process.env.WEB_BASE_URL}/activate/${user.activation.id}
|
||||||
`;
|
`;
|
||||||
sendgrid.send({
|
sendgrid.send({
|
||||||
to: user.email,
|
to: user.email,
|
||||||
subject: "Welcome to Hostr",
|
subject: 'Welcome to Hostr',
|
||||||
from,
|
from,
|
||||||
fromname,
|
fromname,
|
||||||
html,
|
html,
|
||||||
text,
|
text,
|
||||||
categories: ["activate"],
|
categories: [
|
||||||
|
'activate',
|
||||||
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function sendResetToken(email) {
|
export async function sendResetToken(email) {
|
||||||
const user = await models.user.findOne({
|
const user = await models.user.findOne({
|
||||||
where: {
|
where: {
|
||||||
|
@ -157,7 +159,7 @@ export async function sendResetToken(email) {
|
||||||
id: uuid.v4(),
|
id: uuid.v4(),
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
});
|
});
|
||||||
const html = await render("email/inlined/forgot", {
|
const html = await render('email/inlined/forgot', {
|
||||||
forgotUrl: `${process.env.WEB_BASE_URL}/forgot/${reset.id}`,
|
forgotUrl: `${process.env.WEB_BASE_URL}/forgot/${reset.id}`,
|
||||||
});
|
});
|
||||||
const text = `It seems you've forgotten your password :(
|
const text = `It seems you've forgotten your password :(
|
||||||
|
@ -165,32 +167,38 @@ Visit ${process.env.WEB_BASE_URL}/forgot/${reset.id} to set a new one.
|
||||||
`;
|
`;
|
||||||
sendgrid.send({
|
sendgrid.send({
|
||||||
to: user.email,
|
to: user.email,
|
||||||
from: "jonathan@hostr.co",
|
from: 'jonathan@hostr.co',
|
||||||
fromname: "Jonathan from Hostr",
|
fromname: 'Jonathan from Hostr',
|
||||||
subject: "Hostr Password Reset",
|
subject: 'Hostr Password Reset',
|
||||||
html,
|
html,
|
||||||
text,
|
text,
|
||||||
categories: ["password-reset"],
|
categories: [
|
||||||
|
'password-reset',
|
||||||
|
],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new Error("There was an error looking up your email address.");
|
throw new Error('There was an error looking up your email address.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function fromToken(token) {
|
export async function fromToken(token) {
|
||||||
const userId = await this.redis.get(token);
|
const userId = await this.redis.get(token);
|
||||||
return models.user.findByPk(userId);
|
return models.user.findByPk(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function fromCookie(rememberId) {
|
export async function fromCookie(rememberId) {
|
||||||
const userId = await models.remember.findByPk(rememberId);
|
const userId = await models.remember.findByPk(rememberId);
|
||||||
return models.user.findByPk(userId);
|
return models.user.findByPk(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function validateResetToken(resetId) {
|
export async function validateResetToken(resetId) {
|
||||||
return models.reset.findByPk(resetId);
|
return models.reset.findByPk(resetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function updatePassword(userId, password) {
|
export async function updatePassword(userId, password) {
|
||||||
const cryptedPassword = await passwords.crypt(password);
|
const cryptedPassword = await passwords.crypt(password);
|
||||||
const user = await models.user.findByPk(userId);
|
const user = await models.user.findByPk(userId);
|
||||||
|
@ -198,6 +206,7 @@ export async function updatePassword(userId, password) {
|
||||||
await user.save();
|
await user.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function activateUser(code) {
|
export async function activateUser(code) {
|
||||||
const activation = await models.activation.findOne({
|
const activation = await models.activation.findOne({
|
||||||
where: {
|
where: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue