(wip: auth)
Some checks are pending
SSH Deploy to staging / remote-update (push) Waiting to run

This commit is contained in:
Sheldon Cooper 2026-08-13 22:23:29 -04:00
parent da7d75641d
commit 81f86acc7b
7 changed files with 148 additions and 18 deletions

View file

@ -1,4 +1,4 @@
let HOST = 'http://localhost:1225'
let HOST = '' //blank for same-origin
document.addEventListener("alpine:init", () => {
Alpine.store("dictionary", {

View file

@ -26,18 +26,6 @@
--shadow-lg: 0 4px 8px var(--color-shadow);
}
/* Small devices (portrait tablets and large phones, 600px and up) */
@media (max-width: 600px) {
.cards-container {
grid-template-columns: 1fr;
background-color: #fb0;
}
.is-expanded {
grid-row: span 1;
grid-column: span 1;
}
}
* {
margin: 0;
@ -384,3 +372,19 @@ button:disabled{
color: var(--color-text-secondary);
font-size: 0.95rem;
}
/* Small devices (portrait tablets and large phones, 600px and up) */
@media (max-width: 600px) {
.cards-container {
display: flex;
flex-direction: column;
}
.card {
width: 100%;
}
.sidebar {
display: none;
}
}

View file

@ -28,6 +28,7 @@
"google-auth-library": "^9.15.1",
"googleapis": "^149.0.0",
"node-fetch": "^3.3.2",
"passport": "^0.7.0",
"reflect-metadata": "^0.2.2",
"sqlite3": "^5.1.7",
"typeorm": "0.3.26",

View file

@ -1,6 +1,6 @@
import "reflect-metadata"
import { DataSource } from "typeorm"
import {Lemma, WordForm, Media, Example, Definition, Comment, PartOfSpeech, Lect} from "../db/dbmodel.js"
import {Lemma, WordForm, Media, Example, Definition, Comment, PartOfSpeech, Lect, Role, User} from "../db/dbmodel.js"
const persistent_path = process.env.VI_DB_PERSISTENT_PATH || "./res";
@ -9,7 +9,7 @@ export const appDataSource = new DataSource({
database:`${persistent_path}/dev.sqlite`,
synchronize: true,
logging: false,
entities: [Lemma, WordForm, Example, Media, Definition, Comment, PartOfSpeech, Lect],
entities: [Lemma, WordForm, Example, Media, Definition, Comment, PartOfSpeech, Lect, Role, User],
migrations: [],
subscribers: [],
})

View file

@ -116,3 +116,24 @@ export class PartOfSpeech extends BaseEntity {
@Column({ nullable: false, unique: true, type: "text" })
short_form: string;
}
@Entity()
export class User extends BaseEntity {
@PrimaryColumn({ type: "text", nullable: false })
user_name: string;
@ManyToMany(() => Role, (role) => role.users, {eager:true})
@JoinTable()
roles: Role[];
}
@Entity()
export class Role extends BaseEntity {
@PrimaryColumn({ type: "text", nullable: false})
role_name: string;
@ManyToMany(() => User, (user) => user.roles, {eager:true})
@JoinTable()
users: User[];
}

View file

@ -1,16 +1,19 @@
import "reflect-metadata";
import { SAMPLE } from "@repo/common/sample";
import path from "path"
import { fileURLToPath } from 'url';
import express from "express";
import crypto from "crypto";
import fs from "fs";
import { appDataSource } from "./config/dbconfig.js";
import { Lemma, WordForm, Lect, Definition, Example } from "./db/dbmodel.js";
import { Lemma, WordForm, Lect, Definition, Example, Role, User } from "./db/dbmodel.js";
import "@total-typescript/ts-reset";
import { Like, In } from "typeorm";
import cors from "cors";
const RELOAD_SHEET_ON_START = false;
const SOURCE_FILE = "res/sample.tsv";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
appDataSource
.initialize()
@ -19,15 +22,86 @@ appDataSource
if (RELOAD_SHEET_ON_START) {
await loadSheet();
await ensureDefaultRoles();
}
})
.catch((error) => console.log(error));
async function ensureDefaultRoles(){
const ADMIN_NAME = "admin"
const EDITOR_NAME = "editor"
const READER_NAME = "reader"
let admin_role = new Role();
admin_role.role_name = ADMIN_NAME;
let editor_role = new Role();
editor_role.role_name = EDITOR_NAME;
let reader_role = new Role();
reader_role.role_name = READER_NAME;
Role.save([admin_role, editor_role, reader_role]);
let admin_user: User;
let editor_user: User;
let reader_user: User;
await User.findOne({where:
{user_name:ADMIN_NAME}
}).then(async (u)=>{
//if no admin user is detected, generate one with the admin role
if (!u){
admin_user = new User();
admin_user.user_name = ADMIN_NAME;
admin_user.roles = [admin_role];
await admin_user
.save()
.then((u)=>{
admin_user = u;
});
}
})
await User.findOne({where:
{user_name:EDITOR_NAME}
}).then(async (u)=>{
if (!u){
editor_user = new User();
editor_user.user_name = EDITOR_NAME;
editor_user.roles = [editor_role];
await editor_user
.save()
.then((u)=>{
editor_user = u;
});
}
})
await User.findOne({where:
{user_name:READER_NAME}
}).then(async (u)=>{
if (!u){
reader_user = new User();
reader_user.user_name = READER_NAME;
reader_user.roles = [reader_role];
await reader_user
.save()
.then((u)=>{
reader_user = u;
});
}
})
}
function initExpress() {
const app = express();
const PORT = 1225;
app.use(cors(), express.json());
console.info(path.join(__dirname, '../../ktb-static'));
app.use(express.json(), express.static(path.join(__dirname, '../../ktb-static')));
app.get("/sample", (_req, res) => {
res.status(200).send(SAMPLE);