dev
This commit is contained in:
+546
-9
@@ -2,6 +2,14 @@ import bcrypt from 'bcrypt';
|
||||
import sql from '$lib/db/db.server';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { saveAvatar } from '$lib/index.server';
|
||||
import {
|
||||
EmploymentType,
|
||||
type User,
|
||||
type Company,
|
||||
type Tag,
|
||||
type Posting,
|
||||
type Application
|
||||
} from '$lib/types';
|
||||
|
||||
export async function createUser(user: User): Promise<number> {
|
||||
const password_hash: string = await bcrypt.hash(user.password!, 12);
|
||||
@@ -48,7 +56,7 @@ export async function updateUser(user: User): Promise<number> {
|
||||
|
||||
export async function checkUserCreds(username: string, password: string): Promise<User | null> {
|
||||
const [user] = await sql`
|
||||
SELECT id, password_hash, perms, active
|
||||
SELECT id, username, password_hash, perms, active, company_id AS "companyId"
|
||||
FROM users
|
||||
WHERE username = ${username}
|
||||
`;
|
||||
@@ -57,7 +65,8 @@ export async function checkUserCreds(username: string, password: string): Promis
|
||||
return null;
|
||||
}
|
||||
if (await bcrypt.compare(password, user.password_hash)) {
|
||||
return <User>{ id: user.id, perms: user.perms, active: user.active };
|
||||
delete user.password_hash;
|
||||
return <User>user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -87,6 +96,19 @@ export async function getUsers(searchQuery: string | null = null): Promise<User[
|
||||
return <User[]>(<unknown>users);
|
||||
}
|
||||
|
||||
export async function getCompanies(searchQuery: string | null = null): Promise<Company[]> {
|
||||
return sql<Company[]>`
|
||||
SELECT id,
|
||||
name,
|
||||
description,
|
||||
website,
|
||||
company_code AS "companyCode",
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt"
|
||||
FROM companies
|
||||
WHERE name ILIKE ${searchQuery ? `%${searchQuery}%` : '%'};
|
||||
`;
|
||||
}
|
||||
|
||||
// should require MANAGE_USERS permission
|
||||
export async function getUser(id: number): Promise<User> {
|
||||
const [user] = await sql`
|
||||
@@ -152,9 +174,84 @@ export async function getUserWithCompany(id: number): Promise<User> {
|
||||
return <User>user;
|
||||
}
|
||||
|
||||
export async function getUserWithCompanyAndApplications(
|
||||
id: number
|
||||
): Promise<{ user: User; applications: Application[] }> {
|
||||
const data = await sql`
|
||||
WITH company_data AS (
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
website,
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt"
|
||||
FROM companies
|
||||
WHERE id = (SELECT company_id FROM users WHERE id = ${id})
|
||||
),
|
||||
user_data AS (
|
||||
SELECT
|
||||
username,
|
||||
perms,
|
||||
email,
|
||||
phone,
|
||||
full_name AS "fullName",
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
last_signin AT TIME ZONE 'UTC' AS "lastSignIn",
|
||||
active
|
||||
FROM users
|
||||
WHERE "id" = ${id}
|
||||
),
|
||||
application_data AS (
|
||||
SELECT
|
||||
id,
|
||||
posting_id AS "postingId",
|
||||
(SELECT title FROM postings WHERE id = posting_id) AS "postingTitle",
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt"
|
||||
FROM applications
|
||||
WHERE "user_id" = ${id}
|
||||
)
|
||||
SELECT
|
||||
(
|
||||
SELECT row_to_json(company_data)
|
||||
FROM company_data
|
||||
) AS company,
|
||||
(
|
||||
SELECT row_to_json(user_data)
|
||||
FROM user_data
|
||||
) AS user,
|
||||
(
|
||||
SELECT json_agg(row_to_json(application_data))
|
||||
FROM application_data
|
||||
) AS applications;
|
||||
`;
|
||||
|
||||
if (!data) {
|
||||
error(404, 'User not found');
|
||||
}
|
||||
let user = data[0].user;
|
||||
user.company = data[0].company;
|
||||
|
||||
user.createdAt = new Date(user.createdAt);
|
||||
user.lastSignIn = new Date(user.lastSignIn);
|
||||
if (user.company) {
|
||||
user.company.createdAt = new Date(user.company.createdAt);
|
||||
}
|
||||
let applications = data[0].applications;
|
||||
if (applications) {
|
||||
applications.forEach((application: { createdAt: string | number | Date }) => {
|
||||
application.createdAt = new Date(application.createdAt);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
user: <User>user,
|
||||
applications: <Application[]>applications
|
||||
};
|
||||
}
|
||||
|
||||
// should require MANAGE_USERS permission
|
||||
export async function deleteUser(id: number): Promise<void> {
|
||||
const response = await sql`
|
||||
await sql`
|
||||
DELETE FROM users
|
||||
WHERE id = ${id};
|
||||
`;
|
||||
@@ -177,16 +274,456 @@ export async function updateLastSignin(username: string): Promise<void> {
|
||||
`;
|
||||
}
|
||||
|
||||
export async function createCompany(
|
||||
name: string,
|
||||
description: string,
|
||||
website: string
|
||||
): Promise<number> {
|
||||
export async function createCompany(company: Company): 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)))
|
||||
VALUES (${company.name}, ${company.description}, ${company.website}, NOW(), generate_company_code(CAST(CURRVAL('companies_id_seq') AS INT)))
|
||||
RETURNING id;
|
||||
`;
|
||||
|
||||
return response[0].id;
|
||||
}
|
||||
|
||||
export async function editCompany(company: Company): Promise<number> {
|
||||
const response = await sql`
|
||||
UPDATE companies
|
||||
SET name = ${company.name}, description = ${company.description}, website = ${company.website}
|
||||
WHERE id = ${company.id}
|
||||
RETURNING id;
|
||||
`;
|
||||
|
||||
return response[0].id;
|
||||
}
|
||||
|
||||
export async function deleteCompany(id: number): Promise<void> {
|
||||
await sql`
|
||||
DELETE FROM companies
|
||||
WHERE id = ${id};
|
||||
`;
|
||||
}
|
||||
|
||||
export async function getCompany(id: number): Promise<Company> {
|
||||
const [company] = await sql`
|
||||
SELECT id, name, description, website, created_at AS "createdAt"
|
||||
FROM companies
|
||||
WHERE id = ${id};
|
||||
`;
|
||||
|
||||
if (!company) {
|
||||
error(404, 'Company not found');
|
||||
}
|
||||
|
||||
return <Company>company;
|
||||
}
|
||||
|
||||
export async function getCompanyFullData(
|
||||
id: number
|
||||
): Promise<{ company: Company; users: User[]; postings: Posting[] }> {
|
||||
const data = await sql`
|
||||
WITH company_data AS (
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
website,
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt"
|
||||
FROM companies
|
||||
WHERE id = ${id}
|
||||
),
|
||||
user_data AS (
|
||||
SELECT
|
||||
username,
|
||||
email,
|
||||
phone,
|
||||
full_name AS "fullName"
|
||||
FROM users
|
||||
WHERE "company_id" = ${id}
|
||||
),
|
||||
posting_data AS (
|
||||
SELECT
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
employer_id AS "employerId",
|
||||
address,
|
||||
employment_type AS "employmentType",
|
||||
wage,
|
||||
link,
|
||||
tag_ids AS "tagIds",
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
updated_at AT TIME ZONE 'UTC' AS "updatedAt",
|
||||
flyer_link AS "flyerLink"
|
||||
FROM postings
|
||||
WHERE "company_id" = ${id}
|
||||
)
|
||||
SELECT
|
||||
(
|
||||
SELECT row_to_json(company_data)
|
||||
FROM company_data
|
||||
) AS company,
|
||||
(
|
||||
SELECT json_agg(row_to_json(user_data))
|
||||
FROM user_data
|
||||
) AS users,
|
||||
(
|
||||
SELECT json_agg(row_to_json(posting_data))
|
||||
FROM posting_data
|
||||
) AS postings;
|
||||
`;
|
||||
|
||||
if (!data) {
|
||||
error(404, 'Company not found');
|
||||
}
|
||||
if (data[0].company) {
|
||||
data[0].company.createdAt = new Date(data[0].company.createdAt);
|
||||
}
|
||||
if (data[0].postings) {
|
||||
data[0].postings.forEach(
|
||||
(posting: {
|
||||
createdAt: string | number | Date;
|
||||
updatedAt: string | number | Date;
|
||||
tagIds: number[] | undefined;
|
||||
tags: { id: number; displayName: null; createdAt: null }[];
|
||||
}) => {
|
||||
posting.createdAt = new Date(posting.createdAt);
|
||||
posting.updatedAt = new Date(posting.updatedAt);
|
||||
if (posting.tagIds) {
|
||||
posting.tagIds?.forEach((tagId: number) => {
|
||||
posting.tags.push({ id: tagId, displayName: null, createdAt: null });
|
||||
});
|
||||
}
|
||||
delete posting.tagIds;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
company: <Company>data[0].company,
|
||||
users: <User[]>data[0].users,
|
||||
postings: <Posting[]>data[0].postings
|
||||
};
|
||||
}
|
||||
|
||||
export async function createPosting(posting: Posting): Promise<number> {
|
||||
if (posting.tagIds === null || posting.tagIds === undefined) {
|
||||
posting.tagIds = [];
|
||||
}
|
||||
posting.tags?.forEach((tag) => {
|
||||
posting.tagIds?.push(tag.id);
|
||||
});
|
||||
if (posting.companyId === null || posting.companyId === undefined) {
|
||||
if (posting.company) {
|
||||
posting.companyId = posting.company.id;
|
||||
} else {
|
||||
posting.companyId = null;
|
||||
}
|
||||
}
|
||||
const response = await sql`
|
||||
INSERT INTO postings (title, description, employer_id, address, employment_type, wage, link, tag_ids, created_at, updated_at, flyer_link, company_id)
|
||||
VALUES (${posting.title}, ${posting.description}, ${posting.employerId}, ${posting.address}, ${posting.employmentType}, ${posting.wage}, ${posting.link}, ${posting.tagIds}, NOW(), NOW(), ${posting.flyerLink}, ${posting.companyId})
|
||||
RETURNING id;
|
||||
`;
|
||||
|
||||
return response[0].id;
|
||||
}
|
||||
|
||||
export async function editPosting(posting: Posting): Promise<number> {
|
||||
if (posting.tagIds === null || posting.tagIds === undefined) {
|
||||
posting.tagIds = [];
|
||||
}
|
||||
posting.tags?.forEach((tag) => {
|
||||
posting.tagIds?.push(tag.id);
|
||||
});
|
||||
if (posting.companyId === null || posting.companyId === undefined) {
|
||||
if (posting.company) {
|
||||
posting.companyId = posting.company.id;
|
||||
} else {
|
||||
posting.companyId = null;
|
||||
}
|
||||
}
|
||||
|
||||
const response = await sql`
|
||||
UPDATE postings
|
||||
SET title = ${posting.title}, description = ${posting.description}, employer_id = ${posting.employerId}, address = ${posting.address}, employment_type = ${posting.employmentType}, wage = ${posting.wage}, link = ${posting.link}, tag_ids = ${posting.tagIds}, updated_at = NOW(), flyer_link = ${posting.flyerLink}, company_id = ${posting.companyId}
|
||||
WHERE id = ${posting.id}
|
||||
RETURNING id;
|
||||
`;
|
||||
|
||||
return response[0].id;
|
||||
}
|
||||
|
||||
export async function deletePosting(id: number): Promise<void> {
|
||||
await sql`
|
||||
DELETE FROM postings
|
||||
WHERE id = ${id};
|
||||
`;
|
||||
}
|
||||
|
||||
export async function getCompanyEmployers(
|
||||
id: number
|
||||
): Promise<{ company: Company; users: User[] }> {
|
||||
const data = await sql`
|
||||
WITH company_data AS (
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
website,
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
company_code AS "companyCode"
|
||||
FROM companies
|
||||
WHERE id = ${id}
|
||||
),
|
||||
user_data AS (SELECT id,
|
||||
username,
|
||||
email,
|
||||
phone,
|
||||
full_name AS "fullName",
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
last_signin AT TIME ZONE 'UTC' AS "lastSignIn",
|
||||
company_id as "companyId"
|
||||
FROM users
|
||||
WHERE "company_code" = (SELECT company_code FROM companies WHERE id = ${id}))
|
||||
SELECT
|
||||
(
|
||||
SELECT row_to_json(company_data)
|
||||
FROM company_data
|
||||
) AS company,
|
||||
(
|
||||
SELECT json_agg(row_to_json(user_data))
|
||||
FROM user_data
|
||||
) AS users;
|
||||
`;
|
||||
|
||||
if (!data) {
|
||||
error(404, 'Company not found');
|
||||
}
|
||||
if (data[0].users) {
|
||||
data[0].users.forEach(
|
||||
(user: {
|
||||
company: { id: any };
|
||||
companyId: any;
|
||||
createdAt: string | number | Date;
|
||||
lastSignIn: string | number | Date;
|
||||
}) => {
|
||||
user.company = {
|
||||
id: user.companyId
|
||||
};
|
||||
user.createdAt = new Date(user.createdAt);
|
||||
user.lastSignIn = new Date(user.lastSignIn);
|
||||
delete user.companyId;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
company: <Company>data[0].company,
|
||||
users: <User[]>data[0].users
|
||||
};
|
||||
}
|
||||
|
||||
export async function removeEmployerFromCompany(companyId: number, userId: number): Promise<void> {
|
||||
await sql`
|
||||
UPDATE users
|
||||
SET company_id = NULL,
|
||||
company_code = NULL
|
||||
WHERE id = ${userId};
|
||||
`;
|
||||
}
|
||||
|
||||
export async function addEmployerToCompany(companyId: number, userId: number): Promise<void> {
|
||||
await sql`
|
||||
UPDATE users
|
||||
SET company_id = ${companyId}
|
||||
WHERE id = ${userId};
|
||||
`;
|
||||
}
|
||||
|
||||
export async function getPostings(searchQuery: string | null = null): Promise<Posting[]> {
|
||||
const postings = await sql<Posting[]>`
|
||||
SELECT p.id,
|
||||
p.title,
|
||||
p.description,
|
||||
p.employer_id AS "employerId",
|
||||
p.address,
|
||||
p.employment_type AS "employmentType",
|
||||
p.wage,
|
||||
p.link,
|
||||
p.tag_ids AS "tagIds",
|
||||
p.created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
p.updated_at AT TIME ZONE 'UTC' AS "updatedAt",
|
||||
p.flyer_link AS "flyerLink",
|
||||
p.company_id AS "companyId",
|
||||
c.name AS "companyName"
|
||||
FROM postings p
|
||||
LEFT JOIN companies c ON p.company_id = c.id
|
||||
WHERE title ILIKE ${searchQuery ? `%${searchQuery}%` : '%'};
|
||||
`;
|
||||
postings.forEach((posting) => {
|
||||
posting.company = <Company>{};
|
||||
if (posting.companyName) {
|
||||
posting.company.name = posting.companyName;
|
||||
}
|
||||
delete posting.companyName;
|
||||
posting.tags = [];
|
||||
|
||||
posting.employmentType = EmploymentType[posting.employmentType as keyof typeof EmploymentType];
|
||||
if (posting.tagIds) {
|
||||
posting.tagIds?.forEach((tagId: number) => {
|
||||
posting.tags.push({ id: tagId, displayName: null, createdAt: null });
|
||||
});
|
||||
}
|
||||
delete posting.tagIds;
|
||||
});
|
||||
return <Posting[]>(<unknown>postings);
|
||||
}
|
||||
|
||||
export async function getPosting(id: number): Promise<Posting> {
|
||||
const data = await sql<Posting[]>`
|
||||
SELECT id,
|
||||
title,
|
||||
description,
|
||||
employer_id AS "employerId",
|
||||
address,
|
||||
employment_type AS "employmentType",
|
||||
wage,
|
||||
link,
|
||||
tag_ids AS "tagIds",
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
updated_at AT TIME ZONE 'UTC' AS "updatedAt",
|
||||
flyer_link AS "flyerLink",
|
||||
company_id AS "companyId"
|
||||
FROM postings
|
||||
WHERE id = ${id};
|
||||
`;
|
||||
const posting = data[0];
|
||||
posting.tags = [];
|
||||
posting.employmentType = EmploymentType[posting.employmentType as keyof typeof EmploymentType];
|
||||
if (posting.tagIds) {
|
||||
posting.tagIds?.forEach((tagId: number) => {
|
||||
posting.tags.push({ id: tagId, displayName: null, createdAt: null });
|
||||
});
|
||||
}
|
||||
delete posting.tagIds;
|
||||
|
||||
if (posting.createdAt) {
|
||||
posting.createdAt = new Date(posting.createdAt);
|
||||
}
|
||||
if (posting.updatedAt) {
|
||||
posting.updatedAt = new Date(posting.updatedAt);
|
||||
}
|
||||
|
||||
return posting;
|
||||
}
|
||||
|
||||
export async function getPostingFullData(id: number): Promise<Posting> {
|
||||
const data = await sql`
|
||||
WITH company_data AS (
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
website,
|
||||
created_at AS "createdAt"
|
||||
FROM companies
|
||||
WHERE id = (SELECT company_id FROM postings WHERE id = ${id})
|
||||
),
|
||||
user_data AS (
|
||||
SELECT
|
||||
username,
|
||||
email,
|
||||
phone,
|
||||
full_name AS "fullName"
|
||||
FROM users
|
||||
WHERE "company_id" = (SELECT company_id FROM postings WHERE id = ${id})
|
||||
),
|
||||
posting_data AS (
|
||||
SELECT
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
employer_id AS "employerId",
|
||||
address,
|
||||
employment_type AS "employmentType",
|
||||
wage,
|
||||
link,
|
||||
tag_ids AS "tagIds",
|
||||
created_at AT TIME ZONE 'UTC' AS "createdAt",
|
||||
updated_at AT TIME ZONE 'UTC' AS "updatedAt",
|
||||
flyer_link AS "flyerLink"
|
||||
FROM postings
|
||||
WHERE id = ${id}
|
||||
)
|
||||
SELECT
|
||||
(
|
||||
SELECT row_to_json(company_data)
|
||||
FROM company_data
|
||||
) AS company,
|
||||
(
|
||||
SELECT row_to_json(user_data)
|
||||
FROM user_data
|
||||
) AS user,
|
||||
(
|
||||
SELECT row_to_json(posting_data)
|
||||
FROM posting_data
|
||||
) AS posting;
|
||||
`;
|
||||
|
||||
if (!data) {
|
||||
error(404, 'Posting not found');
|
||||
}
|
||||
let posting = <Posting>data[0].posting;
|
||||
posting.company = <Company>data[0].company;
|
||||
posting.employer = <User>data[0].user;
|
||||
|
||||
if (posting.createdAt) {
|
||||
posting.createdAt = new Date(posting.createdAt);
|
||||
}
|
||||
if (posting.updatedAt) {
|
||||
posting.updatedAt = new Date(posting.updatedAt);
|
||||
}
|
||||
|
||||
return posting;
|
||||
}
|
||||
|
||||
export async function createApplication(application: Application): Promise<number> {
|
||||
const response = await sql`
|
||||
INSERT INTO applications (posting_id, user_id, candidate_statement, created_at)
|
||||
VALUES (${application.postingId}, ${application.userId}, ${application.candidateStatement}, NOW())
|
||||
RETURNING id;
|
||||
`;
|
||||
|
||||
return response[0].id;
|
||||
}
|
||||
|
||||
export async function deleteApplication(id: number): Promise<void> {
|
||||
const response = await sql`
|
||||
DELETE FROM applications
|
||||
WHERE id = ${id};
|
||||
`;
|
||||
}
|
||||
|
||||
export async function deleteApplicationWithUser(
|
||||
applicationId: number,
|
||||
userId: number
|
||||
): Promise<void> {
|
||||
console.log(applicationId, userId);
|
||||
const response = await sql`
|
||||
DELETE FROM applications
|
||||
WHERE id = ${applicationId} AND user_id = ${userId};
|
||||
`;
|
||||
}
|
||||
|
||||
export async function getApplications(postingId: number): Promise<Application[]> {
|
||||
const applications = await sql<Application[]>`
|
||||
SELECT id, posting_id AS "postingId", user_id AS "userId", candidate_statement AS "candidateStatement", created_at AS "createdAt"
|
||||
FROM applications
|
||||
WHERE posting_id = ${postingId};
|
||||
`;
|
||||
|
||||
applications.forEach((application) => {
|
||||
application.createdAt = new Date(application.createdAt);
|
||||
});
|
||||
|
||||
return applications;
|
||||
}
|
||||
|
||||
+21
-1
@@ -3,7 +3,7 @@ import path from 'path';
|
||||
import fetch from 'node-fetch';
|
||||
import { type Cookies, error } from '@sveltejs/kit';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { getUserWithCompany } from '$lib/db/index.server';
|
||||
import type { User } from '$lib/types';
|
||||
|
||||
// TODO: Handle saving custom avatar uploads
|
||||
export async function saveAvatar(user: User): Promise<void> {
|
||||
@@ -14,6 +14,7 @@ export async function saveAvatar(user: User): Promise<void> {
|
||||
fs.writeFileSync(filePath, avatar);
|
||||
}
|
||||
|
||||
// TODO: change to return null instead of -1
|
||||
export function getUserPerms(cookies: Cookies): number {
|
||||
if (process.env.JWT_SECRET === undefined) {
|
||||
throw new Error('JWT_SECRET not defined');
|
||||
@@ -51,3 +52,22 @@ export function getUserId(cookies: Cookies): number {
|
||||
}
|
||||
error(403, 'Unauthorized');
|
||||
}
|
||||
|
||||
export function getUserCompanyId(cookies: Cookies): number | null {
|
||||
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' && 'companyId' in decoded) {
|
||||
return decoded['companyId'];
|
||||
}
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
error(403, 'Unauthorized');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { Cookies } from '@sveltejs/kit';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import type { User } from '$lib/types';
|
||||
|
||||
export function setJWT(cookies: Cookies, user: User) {
|
||||
const payload = {
|
||||
username: user.username,
|
||||
perms: user.perms,
|
||||
id: user.id,
|
||||
companyId: user.companyId
|
||||
};
|
||||
|
||||
if (process.env.JWT_SECRET === undefined) {
|
||||
throw new Error('JWT_SECRET not defined');
|
||||
}
|
||||
|
||||
const maxAge = 60 * 60 * 24 * 30; // 30 days
|
||||
const JWT = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' });
|
||||
cookies.set('jwt', JWT, { maxAge, path: '/', httpOnly: false });
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
import { PERMISSIONS } from '$lib/consts';
|
||||
import type { EmploymentType } from '$lib/types';
|
||||
|
||||
export let userState = $state({ perms: PERMISSIONS.VIEW, username: null, id: null });
|
||||
export let userState = $state({
|
||||
perms: PERMISSIONS.VIEW,
|
||||
username: null,
|
||||
id: null,
|
||||
companyId: null
|
||||
});
|
||||
|
||||
export const userPerms = PERMISSIONS.VIEW | PERMISSIONS.APPLY_FOR_JOBS;
|
||||
export const employerPerms = PERMISSIONS.SUBMIT_POSTINGS | PERMISSIONS.MANAGE_EMPLOYERS;
|
||||
@@ -19,3 +25,28 @@ export function telFormatter(initial: string) {
|
||||
(num.length > 6 ? '-' + num.substring(6, 10) : '');
|
||||
return initial;
|
||||
}
|
||||
|
||||
export const getCookieValue = (name: String) =>
|
||||
document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop() || '';
|
||||
|
||||
export function updateUserState() {
|
||||
const JWT = getCookieValue('jwt');
|
||||
if (JWT !== '') {
|
||||
const state = JSON.parse(atob(JWT.split('.')[1]));
|
||||
userState.perms = state.perms;
|
||||
userState.username = state.username;
|
||||
userState.id = state.id;
|
||||
userState.companyId = state.companyId;
|
||||
}
|
||||
}
|
||||
|
||||
export function employmentTypeDisplayName(type: EmploymentType) {
|
||||
switch (type) {
|
||||
case 'full_time':
|
||||
return 'Full Time';
|
||||
case 'part_time':
|
||||
return 'Part Time';
|
||||
case 'internship':
|
||||
return 'Internship';
|
||||
}
|
||||
}
|
||||
|
||||
+46
-6
@@ -1,4 +1,4 @@
|
||||
interface User {
|
||||
export interface User {
|
||||
id: number | null;
|
||||
username: string;
|
||||
password: string | null;
|
||||
@@ -11,18 +11,58 @@ interface User {
|
||||
fullName: string | null;
|
||||
company: Company | null;
|
||||
companyCode: string | null;
|
||||
companyId: number | null | undefined;
|
||||
}
|
||||
|
||||
interface Tag {
|
||||
export interface Company {
|
||||
id: number;
|
||||
displayName: string;
|
||||
name: string | null;
|
||||
description: string | null;
|
||||
website: string | null;
|
||||
createdAt: Date | null;
|
||||
companyCode: string | null;
|
||||
}
|
||||
|
||||
interface Company {
|
||||
export interface Posting {
|
||||
id: number;
|
||||
name: string;
|
||||
title: string;
|
||||
description: string;
|
||||
website: string;
|
||||
employerId: number;
|
||||
address: string;
|
||||
employmentType: EmploymentType;
|
||||
wage: string;
|
||||
link: string;
|
||||
tags: Tag[];
|
||||
tagIds: number[] | null | undefined;
|
||||
createdAt: Date | null;
|
||||
updatedAt: Date | null;
|
||||
flyerLink: string | null;
|
||||
company: Company;
|
||||
companyId: number | null | undefined;
|
||||
companyName: string | null | undefined;
|
||||
employer: User | null | undefined;
|
||||
}
|
||||
|
||||
export interface Tag {
|
||||
id: number;
|
||||
displayName: string | null;
|
||||
createdAt: Date | null;
|
||||
}
|
||||
|
||||
export enum EmploymentType {
|
||||
full_time = 'full_time',
|
||||
part_time = 'part_time',
|
||||
internship = 'internship'
|
||||
// contract = 'Contract',
|
||||
// temporary = 'Temporary',
|
||||
// seasonal = 'Seasonal'
|
||||
}
|
||||
|
||||
export interface Application {
|
||||
id: number;
|
||||
userId: number;
|
||||
postingId: number;
|
||||
postingTitle: string | null;
|
||||
candidateStatement: string;
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user