adbcc4b9af
feat: implement conversations API with message retrieval and posting feat: add avatar URL handling for users and update user role definitions feat: create chat system tables in the database with initial seed data fix: update user roles from "sales_user" to "sales" for consistency chore: add middleware for system API route access fixed fuckups on john's side, added a benchmark Made Graphs actualy load from database and realtime data, graphs will update and percentages will be mathematically made, and made realtime added chatcart edits, made graphs glow. added in some little small home feeling fuctions added in a slide show, in login with qoutes from creators because i want to leave a print on it saying we made this shit, we built it brick for brick login page added qoutes some random, and made them shuffle from left to right one dissapears other come in adding shape to the textbox for the qoutes Fixed my chat fuckups when it comes to chats
79 lines
2.9 KiB
TypeScript
79 lines
2.9 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server"
|
|
import { query } from "@/lib/db"
|
|
import { hashPassword, getSessionUser } from "@/lib/auth"
|
|
|
|
export async function GET() {
|
|
try {
|
|
const result = await query(
|
|
`SELECT u.id, u.username, u.email, u.first_name, u.last_name,
|
|
u.is_active AS active, u.created_at, u.avatar_url,
|
|
r.name AS role
|
|
FROM users u
|
|
JOIN user_roles ur ON ur.user_id = u.id
|
|
JOIN roles r ON r.id = ur.role_id
|
|
WHERE u.deleted_at IS NULL
|
|
ORDER BY u.created_at DESC`
|
|
)
|
|
const users = result.rows.map((row: any) => ({
|
|
id: row.id,
|
|
name: `${row.first_name} ${row.last_name}`,
|
|
email: row.email,
|
|
role: row.role.toLowerCase(),
|
|
active: row.active,
|
|
avatar: row.avatar_url || `https://ui-avatars.com/api/?name=${encodeURIComponent(`${row.first_name}+${row.last_name}`)}&background=1d4ed8&color=fff&size=128`,
|
|
createdAt: row.created_at,
|
|
}))
|
|
return NextResponse.json({ users }, { status: 200 })
|
|
} catch (error) {
|
|
console.error("Error fetching users:", error)
|
|
return NextResponse.json({ error: "Failed to fetch users" }, { status: 500 })
|
|
}
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const sessionUser = await getSessionUser()
|
|
if (!sessionUser) {
|
|
return NextResponse.json({ error: "Not authenticated" }, { status: 401 })
|
|
}
|
|
|
|
const { name, email, password, role, active } = await request.json()
|
|
if (!name || !email || !password || !role) {
|
|
return NextResponse.json({ error: "Name, email, password, and role are required" }, { status: 400 })
|
|
}
|
|
|
|
const nameParts = name.trim().split(/\s+/)
|
|
const firstName = nameParts[0]
|
|
const lastName = nameParts.slice(1).join(" ") || firstName
|
|
const username = email.split("@")[0]
|
|
const passwordHash = await hashPassword(password)
|
|
|
|
const result = await query(
|
|
`INSERT INTO users (username, email, password_hash, first_name, last_name, is_active, created_by)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
RETURNING id`,
|
|
[username.toLowerCase(), email.toLowerCase(), passwordHash, firstName, lastName, active, sessionUser.id]
|
|
)
|
|
|
|
const roleId = (
|
|
await query(`SELECT id FROM roles WHERE LOWER(name) = LOWER($1)`, [role])
|
|
).rows[0]?.id
|
|
|
|
if (roleId) {
|
|
await query(
|
|
`INSERT INTO user_roles (user_id, role_id, assigned_by)
|
|
VALUES ($1, $2, $3)`,
|
|
[result.rows[0].id, roleId, sessionUser.id]
|
|
)
|
|
}
|
|
|
|
return NextResponse.json({ success: true, id: result.rows[0].id }, { status: 201 })
|
|
} catch (error: any) {
|
|
console.error("Error creating user:", error)
|
|
if (error?.constraint === "uq_users_username" || error?.constraint === "uq_users_email") {
|
|
return NextResponse.json({ error: "A user with this email or username already exists" }, { status: 409 })
|
|
}
|
|
return NextResponse.json({ error: error?.message || "Failed to create user" }, { status: 500 })
|
|
}
|
|
}
|