dev
This commit is contained in:
+166
-74
@@ -1,100 +1,192 @@
|
||||
import bcrypt from 'bcrypt';
|
||||
import sql from '$lib/db/db.server';
|
||||
import type { Cookies } from '@sveltejs/kit';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { saveAvatar } from '$lib/index.server';
|
||||
|
||||
export async function createUser(username: string, password: string): Promise<void> {
|
||||
const password_hash: string = await bcrypt.hash(password, 12);
|
||||
const timestamp = new Date(Date.now()).toISOString();
|
||||
|
||||
console.log(timestamp);
|
||||
export async function createUser(user: User): Promise<number> {
|
||||
const password_hash: string = await bcrypt.hash(user.password!, 12);
|
||||
|
||||
const response = await sql`
|
||||
INSERT INTO users (username, password_hash, perms, created_at, last_signin, active)
|
||||
VALUES (${username}, ${password_hash}, 3, ${timestamp}, ${timestamp}, ${true});
|
||||
INSERT INTO users (username, password_hash, perms, created_at, last_signin, active, email, phone, full_name, company_code)
|
||||
VALUES (${user.username}, ${password_hash}, ${user.perms}, NOW(), NOW(), ${user.active}, ${user.email}, ${user.phone}, ${user.fullName}, ${user.companyCode})
|
||||
RETURNING id;
|
||||
`;
|
||||
|
||||
// TODO: handle custom image uploads
|
||||
user.id = response[0].id;
|
||||
await saveAvatar(user);
|
||||
|
||||
return response[0].id;
|
||||
}
|
||||
|
||||
export async function checkUserCreds(username: string, password: string): Promise<number> {
|
||||
export async function updateUser(user: User): Promise<number> {
|
||||
let password_hash: string | null = null;
|
||||
|
||||
// Hash the password if provided
|
||||
if (user.password) {
|
||||
password_hash = await bcrypt.hash(user.password, 12);
|
||||
}
|
||||
|
||||
// Construct the SQL query
|
||||
const response = await sql`UPDATE users
|
||||
SET
|
||||
username = ${user.username},
|
||||
perms = ${user.perms},
|
||||
active = ${user.active},
|
||||
${password_hash !== null ? sql`password_hash = ${password_hash},` : sql``}
|
||||
email = ${user.email},
|
||||
phone = ${user.phone},
|
||||
full_name = ${user.fullName},
|
||||
company_code = ${user.companyCode}
|
||||
WHERE id = ${user.id}
|
||||
RETURNING id;`;
|
||||
|
||||
await saveAvatar(user);
|
||||
|
||||
return response[0].id;
|
||||
}
|
||||
|
||||
export async function checkUserCreds(username: string, password: string): Promise<User | null> {
|
||||
const [user] = await sql`
|
||||
SELECT password_hash, perms
|
||||
SELECT id, password_hash, perms, active
|
||||
FROM users
|
||||
WHERE username = ${username}
|
||||
`;
|
||||
|
||||
if (!user) {
|
||||
return -1;
|
||||
return null;
|
||||
}
|
||||
if (await bcrypt.compare(password, user.password_hash)) {
|
||||
return user['perms'];
|
||||
return <User>{ id: user.id, perms: user.perms, active: user.active };
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
export function getUserPerms(cookies: Cookies): number {
|
||||
if (process.env.JWT_SECRET === undefined) {
|
||||
throw new Error('JWT_SECRET not defined');
|
||||
}
|
||||
|
||||
const JWT = cookies.get('jwt');
|
||||
if (JWT) {
|
||||
try {
|
||||
const decoded = jwt.verify(JWT, process.env.JWT_SECRET);
|
||||
if (typeof decoded === 'object' && 'perms' in decoded) {
|
||||
return decoded['perms'];
|
||||
}
|
||||
} catch (err) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return null;
|
||||
}
|
||||
|
||||
// should require MANAGE_USERS permission
|
||||
export async function getUsers(): Promise<User[]> {
|
||||
const users = await sql<
|
||||
{
|
||||
id: number;
|
||||
username: string;
|
||||
perms: number;
|
||||
created_at: Date;
|
||||
last_signin: Date;
|
||||
active: boolean;
|
||||
}[]
|
||||
>`
|
||||
SELECT id, username, perms,
|
||||
created_at AT TIME ZONE 'UTC' AS created_at,
|
||||
last_signin AT TIME ZONE 'UTC' AS last_signin,
|
||||
active
|
||||
FROM users;
|
||||
export async function getUsers(searchQuery: string | null = null): Promise<User[]> {
|
||||
const users = await sql`
|
||||
SELECT id,
|
||||
username,
|
||||
perms,
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
last_signin AT TIME ZONE 'UTC' AS "lastSignIn",
|
||||
active,
|
||||
email,
|
||||
phone,
|
||||
full_name AS "fullName",
|
||||
company_id
|
||||
FROM users
|
||||
WHERE username ILIKE ${searchQuery ? `%${searchQuery}%` : '%'};
|
||||
`;
|
||||
users.forEach((user) => {
|
||||
user.company = {
|
||||
id: user.company_id
|
||||
};
|
||||
delete user.company_id;
|
||||
});
|
||||
return <User[]>(<unknown>users);
|
||||
}
|
||||
|
||||
// should require MANAGE_USERS permission
|
||||
export async function getUser(id: number): Promise<User> {
|
||||
const [user] = await sql`
|
||||
SELECT id, username, perms,
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
last_signin AT TIME ZONE 'UTC' AS "lastSignIn",
|
||||
active, email, phone, full_name AS "fullName", company_id, company_code
|
||||
FROM users
|
||||
WHERE id = ${id};
|
||||
`;
|
||||
if (!user) {
|
||||
error(404, 'User not found');
|
||||
}
|
||||
user.company = {
|
||||
id: user.company_id
|
||||
};
|
||||
delete user.company_id;
|
||||
return <User>user;
|
||||
}
|
||||
|
||||
export async function getUserWithCompany(id: number): Promise<User> {
|
||||
const [user] = await sql`
|
||||
SELECT
|
||||
u.id,
|
||||
u.username,
|
||||
u.perms,
|
||||
u.email,
|
||||
u.phone,
|
||||
u.full_name AS "fullName",
|
||||
u.created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
u.last_signin AT TIME ZONE 'UTC' AS "lastSignIn",
|
||||
u.active,
|
||||
c.id AS company_id,
|
||||
c.name AS company_name,
|
||||
c.description AS company_description,
|
||||
c.website AS company_website,
|
||||
c.created_at AS company_created_at
|
||||
FROM
|
||||
users u
|
||||
LEFT JOIN
|
||||
companies c ON u.company_id = c.id
|
||||
WHERE
|
||||
u.id = ${id};
|
||||
`;
|
||||
if (!user) {
|
||||
error(404, 'User not found');
|
||||
}
|
||||
user.company = {
|
||||
id: user.company_id,
|
||||
name: user.company_name,
|
||||
description: user.company_description,
|
||||
website: user.company_website,
|
||||
createdAt: user.company_created_at
|
||||
};
|
||||
|
||||
// Remove the company-specific columns from the user object
|
||||
delete user.company_id;
|
||||
delete user.company_name;
|
||||
delete user.company_description;
|
||||
delete user.company_website;
|
||||
delete user.company_created_at;
|
||||
|
||||
return <User>user;
|
||||
}
|
||||
|
||||
// should require MANAGE_USERS permission
|
||||
export async function deleteUser(id: number): Promise<void> {
|
||||
const response = await sql`
|
||||
DELETE FROM users
|
||||
WHERE id = ${id};
|
||||
`;
|
||||
return users.map(
|
||||
(user): User => ({
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
perms: user.perms,
|
||||
created_at: user.created_at,
|
||||
last_signin: user.last_signin,
|
||||
active: user.active
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// should require MANAGE_TAGS permission
|
||||
export async function getTags(): Promise<Tag[]> {
|
||||
const tags = await sql<
|
||||
{
|
||||
id: number;
|
||||
display_name: string;
|
||||
}[]
|
||||
>`
|
||||
SELECT id, display_name
|
||||
FROM tags;
|
||||
export async function getTags(searchQuery: string | null): Promise<Tag[]> {
|
||||
return sql<Tag[]>`
|
||||
SELECT id, display_name as "displayName", created_at AT TIME ZONE 'UTC' AS "createdAt"
|
||||
FROM tags
|
||||
WHERE display_name ILIKE ${searchQuery ? `%${searchQuery}%` : '%'};
|
||||
`;
|
||||
return tags.map(
|
||||
(tag): Tag => ({
|
||||
id: tag.id,
|
||||
display_name: tag.display_name
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export async function updateLastSignin(username: string): Promise<void> {
|
||||
await sql`
|
||||
UPDATE users
|
||||
SET last_signin = NOW()
|
||||
WHERE username = ${username};
|
||||
`;
|
||||
}
|
||||
|
||||
export async function createCompany(
|
||||
name: string,
|
||||
description: string,
|
||||
website: string
|
||||
): Promise<number> {
|
||||
const response = await sql`
|
||||
INSERT INTO companies (name, description, website, created_at, company_code)
|
||||
VALUES (${name}, ${description}, ${website}, NOW(), generate_company_code(CAST(CURRVAL('companies_id_seq') AS INT)))
|
||||
RETURNING id;
|
||||
`;
|
||||
|
||||
return response[0].id;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user