Update typos and added scripts

This commit is contained in:
Ryahn 2025-01-27 17:57:51 -05:00
parent cb51c46f63
commit 7db993fb0e
9 changed files with 230 additions and 11 deletions

27
scripts/delete_user.js Normal file
View File

@ -0,0 +1,27 @@
const User = require('../src/db/models/User');
const { Model } = require('objection');
const Knex = require('knex');
const knexConfig = require('../src/config/database');
const knex = Knex(knexConfig.development);
Model.knex(knex);
const email = process.argv[2];
const id = process.argv[3];
if (!email && !id) {
console.error('Usage: node delete_user.js <email> || <id>');
process.exit(1);
}
async function main() {
let user;
if (id) {
user = await User.query().where('id', id).delete();
} else {
user = await User.query().where('email', email).delete();
}
console.log(`User deleted`);
process.exit(0);
}
main();

View File

@ -0,0 +1,36 @@
const bcrypt = require('bcrypt');
const User = require('../src/db/models/User');
const { Model } = require('objection');
const Knex = require('knex');
const knexConfig = require('../src/config/database');
const knex = Knex(knexConfig.development);
Model.knex(knex);
const password = process.argv[2];
const email = process.argv[3];
if (!password && !email) {
console.error('Usage: node generate_password.js <password> [email]');
process.exit(1);
}
async function main() {
let user;
if (email) {
user = await User.query().where('email', email).first();
if (!user) {
console.error('User not found');
process.exit(1);
}
user.password = bcrypt.hashSync(password, 10);
await user.$query().patch();
console.log(`Password updated for user ${user.email}`);
process.exit(0);
} else {
console.log(bcrypt.hashSync(password, 10));
process.exit(0);
}
}
main();

27
scripts/make_user.js Normal file
View File

@ -0,0 +1,27 @@
const User = require('../src/db/models/User');
const { Model } = require('objection');
const Knex = require('knex');
const knexConfig = require('../src/config/database');
const knex = Knex(knexConfig.development);
Model.knex(knex);
const email = process.argv[2];
const password = process.argv[3];
const isAdmin = process.argv[4] === 'true';
if (!email || !password) {
console.error('Usage: node make_user.js <email> <password> [isAdmin]');
process.exit(1);
}
async function main() {
const user = await User.query().insert({
email: email,
password: password,
is_admin: isAdmin
});
console.log(`User created: ${user.email}`);
process.exit(0);
}
main();

View File

@ -0,0 +1,17 @@
exports.up = function(knex) {
return knex.schema.alterTable('temp_emails', table => {
table.dropForeign('user_id');
table.foreign('user_id')
.references('users.id')
.onDelete('CASCADE');
});
};
exports.down = function(knex) {
return knex.schema.alterTable('temp_emails', table => {
table.dropForeign('user_id');
table.foreign('user_id')
.references('users.id');
});
};

View File

@ -6,6 +6,21 @@ class User extends BaseModel {
return 'users';
}
static get relationMappings() {
const TempEmail = require('./TempEmail');
return {
tempEmails: {
relation: BaseModel.HasManyRelation,
modelClass: TempEmail,
join: {
from: 'users.id',
to: 'temp_emails.user_id'
},
onDelete: 'CASCADE'
}
};
}
async $beforeInsert() {
await super.$beforeInsert();
this.password = await bcrypt.hash(this.password, 10);

View File

@ -9,6 +9,8 @@ const config = require('../../config/haraka');
*/
exports.seed = async function(knex) {
await knex('users').del();
await knex('temp_emails').del();
await knex('messages').del();
const hashedPassword = await bcrypt.hash('admin', 10);
const [userId] = await knex('users').insert([

View File

@ -1,9 +1,32 @@
const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const { User } = require('../db/models/User');
const User = require('../db/models/User');
const config = require('../config/haraka');
/**
* @swagger
* /auth/login:
* post:
* summary: Login and get API key
* description: Login with email and password to get an API key
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* email:
* type: string
* description: User's email
* example: user@example.com
* password:
* type: string
* description: User's password
* example: password123
*/
router.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
@ -13,16 +36,41 @@ router.post('/login', async (req, res) => {
return res.status(401).json({ error: 'Invalid credentials' });
}
const token = jwt.sign(
const generateToken = () => {
return jwt.sign(
{ id: user.id, email: user.email, is_admin: user.is_admin },
config.auth.jwtSecret,
{ expiresIn: config.auth.tokenExpiry }
);
};
await User.query().where('id', user.id).update({ api_key: token });
let currentToken = await User.query()
.select('api_key')
.where('id', user.id)
.first();
let token;
if (currentToken && currentToken.api_key) {
try {
jwt.verify(currentToken.api_key, config.auth.jwtSecret);
token = currentToken.api_key;
} catch (tokenError) {
token = generateToken();
await User.query()
.where('id', user.id)
.update({ api_key: token });
}
} else {
token = generateToken();
await User.query()
.where('id', user.id)
.update({ api_key: token });
}
res.json({ token });
} catch (error) {
console.error('Login error:', error);
res.status(500).json({ error: error.message });
}
});

View File

@ -33,7 +33,24 @@ function generateUniqueName() {
return `${formattedName}${randomNumber}`;
}
router.post('/', async (req, res) => {
/**
* @swagger
* /email/generate:
* post:
* summary: Generate a temporary email
* description: Generate a temporary email with a random domain
* requestBody:
* required: false
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* description: Name for the temporary email
*/
router.post('/generate', async (req, res) => {
try {
const randomDomain = await Domain.query()
.where('active', true)
@ -59,14 +76,36 @@ router.post('/', async (req, res) => {
}
});
router.get('/', async (req, res) => {
/**
* @swagger
* /email/list:
* get:
* summary: List all temporary emails
* description: Get a list of all temporary emails for the authenticated user
*/
router.get('/list', async (req, res) => {
const tempEmails = await TempEmail.query().where('user_id', req.user.id);
res.json(tempEmails);
});
router.delete('/:id', async (req, res) => {
/**
* @swagger
* /email/delete/{id}:
* delete:
* summary: Delete a temporary email
* description: Delete a temporary email by its ID
* parameters:
* - in: path
* name: id
* required: true
* description: ID of the temporary email to delete
*/
router.delete('/delete/:id', async (req, res) => {
const tempEmail = await TempEmail.query().where('id', req.params.id).andWhere('user_id', req.user.id).delete();
res.json(tempEmail);
if (!tempEmail) {
res.status(404).json({ status: 'error', message: 'Temp email not found' });
}
res.json({ status: 'success', message: 'Temp email deleted' });
});
module.exports = router;

8
src/routes/index.js Normal file
View File

@ -0,0 +1,8 @@
const express = require('express');
const router = express.Router();
router.get('/', async (req, res) => {
res.json({ message: 'Hello World' });
});
module.exports = router;