add initial user Management API
This commit is contained in:
parent
0816cbe9e5
commit
ffa4496c16
12
src/models/User.ts
Normal file
12
src/models/User.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import mongoose from 'mongoose';
|
||||||
|
|
||||||
|
const UserSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
username: {type: String, required: true, unique: true},
|
||||||
|
pass_hash: {type: String, required: true},
|
||||||
|
salt : {type: String, required: true},
|
||||||
|
access: [String], //rezepte, flims, abrechnung, ...
|
||||||
|
}, {timestamps: true}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const User = mongoose.model("User", UserSchema);
|
54
src/routes/api/login/+server.ts
Normal file
54
src/routes/api/login/+server.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
import { sign } from 'jsonwebtoken';
|
||||||
|
import { hash, verify} from 'argon2';
|
||||||
|
import { COOKIE_SECRET } from '$env/static/private'
|
||||||
|
|
||||||
|
import { dbConnect, dbDisconnect } from '../../../utils/db';
|
||||||
|
import { User } from '../../../models/User';
|
||||||
|
|
||||||
|
// header: use for bearer token for now
|
||||||
|
// recipe json in body
|
||||||
|
export const POST: RequestHandler = async ({request}) => {
|
||||||
|
const {username, password} = await request.json()
|
||||||
|
// TODO: get salt from user in DB
|
||||||
|
await dbConnect()
|
||||||
|
let res = await User.findOne({username: username}, 'pass_hash salt').lean()
|
||||||
|
await dbDisconnect()
|
||||||
|
if(!res){
|
||||||
|
throw error(401, {message: "wrong password or user does not exist"})
|
||||||
|
}
|
||||||
|
|
||||||
|
const stored_pw = res.pass_hash
|
||||||
|
const salt = res.salt
|
||||||
|
|
||||||
|
const isMatch = await verify(stored_pw, password, {salt})
|
||||||
|
if(!isMatch){
|
||||||
|
throw error(401, {message: "wrong password or user does not exist"})
|
||||||
|
}
|
||||||
|
|
||||||
|
res = await createJWT(username)
|
||||||
|
return new Response(JSON.stringify(res))
|
||||||
|
};
|
||||||
|
|
||||||
|
async function hashPassword(password) {
|
||||||
|
try {
|
||||||
|
const salt = await generateSalt(); // Generate a random salt
|
||||||
|
const hashedPassword = await hash(password, salt); // Hash the password with the salt
|
||||||
|
return { hashedPassword, salt };
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error hashing password:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function createJWT(username) {
|
||||||
|
const payload = {
|
||||||
|
username: username,
|
||||||
|
};
|
||||||
|
|
||||||
|
const masterSecret = COOKIE_SECRET;
|
||||||
|
const secretKey = masterSecret;
|
||||||
|
const jwt = sign(payload, secretKey);
|
||||||
|
return jwt
|
||||||
|
}
|
64
src/routes/api/register/+server.ts
Normal file
64
src/routes/api/register/+server.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
import { sign } from 'jsonwebtoken';
|
||||||
|
import { hash, verify } from 'argon2';
|
||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
import { COOKIE_SECRET } from '$env/static/private'
|
||||||
|
import { ALLOW_REGISTRATION } from '$env/static/private'
|
||||||
|
|
||||||
|
import { User } from '../../../models/User';
|
||||||
|
import { dbConnect, dbDisconnect } from '../../../utils/db';
|
||||||
|
|
||||||
|
// header: use for bearer token for now
|
||||||
|
// recipe json in body
|
||||||
|
export const POST: RequestHandler = async ({request}) => {
|
||||||
|
if(ALLOW_REGISTRATION){
|
||||||
|
const {username, password, access} = await request.json()
|
||||||
|
const salt = randomBytes(32).toString('hex'); // Generate a random salt
|
||||||
|
|
||||||
|
const pass_hash = await hashPassword(password, salt)
|
||||||
|
await dbConnect();
|
||||||
|
try{
|
||||||
|
await User.create({
|
||||||
|
username: username,
|
||||||
|
pass_hash: pass_hash,
|
||||||
|
salt: salt,
|
||||||
|
access: access,
|
||||||
|
})
|
||||||
|
}catch(e){
|
||||||
|
await dbDisconnect();
|
||||||
|
throw error(400, e);
|
||||||
|
}
|
||||||
|
await dbDisconnect();
|
||||||
|
return new Response(JSON.stringify({message: "User added successfully"}),
|
||||||
|
{status: 200}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw error(401, "user registration currently closed")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
async function hashPassword(password, salt) {
|
||||||
|
try {
|
||||||
|
const hashedPassword = await hash(password, salt); // Hash the password with the salt
|
||||||
|
return hashedPassword;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error hashing password:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function createJWT(username, userSalt) {
|
||||||
|
const payload = {
|
||||||
|
username: username,
|
||||||
|
};
|
||||||
|
|
||||||
|
const masterSecret = COOKIE_SECRET;
|
||||||
|
const secretKey = masterSecret + userSalt;
|
||||||
|
const jwt = sign(payload, secretKey);
|
||||||
|
return jwt
|
||||||
|
}
|
63
src/routes/api/verify/+server.ts
Normal file
63
src/routes/api/verify/+server.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import type { RequestHandler } from '@sveltejs/kit';
|
||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
import { verify } from 'jsonwebtoken';
|
||||||
|
import { hash} from 'argon2';
|
||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
import { COOKIE_SECRET } from '$env/static/private'
|
||||||
|
import { ALLOW_REGISTRATION } from '$env/static/private'
|
||||||
|
|
||||||
|
import { User } from '../../../models/User';
|
||||||
|
import { dbConnect, dbDisconnect } from '../../../utils/db';
|
||||||
|
|
||||||
|
|
||||||
|
import { getJWTFromRequest } from '../../../utils/cookie';
|
||||||
|
// header: use for bearer token for now
|
||||||
|
// recipe json in body
|
||||||
|
export const GET: RequestHandler = async ({request}) => {
|
||||||
|
const jwt = getJWTFromRequest(request)
|
||||||
|
console.log(jwt)
|
||||||
|
|
||||||
|
// Set your master secret key (replace with your own secret)
|
||||||
|
const masterSecret = COOKIE_SECRET;
|
||||||
|
const secretKey = masterSecret
|
||||||
|
let decoded
|
||||||
|
try{
|
||||||
|
decoded = await verify(jwt, secretKey);
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
throw error(401, "Cookies have changed, please log in again")
|
||||||
|
}
|
||||||
|
|
||||||
|
await dbConnect()
|
||||||
|
let res = await User.findOne({username: decoded.username}, 'access').lean();
|
||||||
|
await dbDisconnect()
|
||||||
|
if(!res){
|
||||||
|
throw error(404, "User for this Cookie does no longer exist")
|
||||||
|
}
|
||||||
|
return new Response(JSON.stringify({
|
||||||
|
username: decoded.username,
|
||||||
|
access: res.access
|
||||||
|
}), {status: 200})
|
||||||
|
};
|
||||||
|
|
||||||
|
async function hashPassword(password, salt) {
|
||||||
|
try {
|
||||||
|
const hashedPassword = await hash(password, salt); // Hash the password with the salt
|
||||||
|
return hashedPassword;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error hashing password:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function createJWT(username, userSalt) {
|
||||||
|
const payload = {
|
||||||
|
username: username,
|
||||||
|
};
|
||||||
|
|
||||||
|
const masterSecret = COOKIE_SECRET;
|
||||||
|
const secretKey = masterSecret + userSalt;
|
||||||
|
const jwt = sign(payload, secretKey);
|
||||||
|
return jwt
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user