Skip to content

Commit

Permalink
add promote-to-admin route
Browse files Browse the repository at this point in the history
  • Loading branch information
vorant94 committed Nov 17, 2024
1 parent 3f45d8a commit acf7e43
Show file tree
Hide file tree
Showing 18 changed files with 317 additions and 37 deletions.
26 changes: 26 additions & 0 deletions drizzle/0002_outgoing_mad_thinker.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
PRAGMA foreign_keys=OFF;--> statement-breakpoint
CREATE TABLE `__new_chains` (
`id` text PRIMARY KEY NOT NULL,
`resource_type` text DEFAULT 'chain' NOT NULL,
`created_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
`updated_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
`name` text NOT NULL
);
--> statement-breakpoint
INSERT INTO `__new_chains`("id", "resource_type", "created_at", "updated_at", "name") SELECT "id", "resource_type", "created_at", "updated_at", "name" FROM `chains`;--> statement-breakpoint
DROP TABLE `chains`;--> statement-breakpoint
ALTER TABLE `__new_chains` RENAME TO `chains`;--> statement-breakpoint
PRAGMA foreign_keys=ON;--> statement-breakpoint
CREATE TABLE `__new_users` (
`id` text PRIMARY KEY NOT NULL,
`resource_type` text DEFAULT 'user' NOT NULL,
`created_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
`updated_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
`telegram_chat_id` integer NOT NULL,
`role` text DEFAULT 'user' NOT NULL
);
--> statement-breakpoint
INSERT INTO `__new_users`("id", "resource_type", "created_at", "updated_at", "telegram_chat_id") SELECT "id", "resource_type", "created_at", "updated_at", "telegram_chat_id" FROM `users`;--> statement-breakpoint
DROP TABLE `users`;--> statement-breakpoint
ALTER TABLE `__new_users` RENAME TO `users`;--> statement-breakpoint
CREATE UNIQUE INDEX `users_telegramChatId_unique` ON `users` (`telegram_chat_id`);
128 changes: 128 additions & 0 deletions drizzle/meta/0002_snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
{
"version": "6",
"dialect": "sqlite",
"id": "132ca062-77cb-4b35-a3c8-3dbe452350ce",
"prevId": "2b4f22d3-5a7a-44b0-85f8-0c48a86ba4e3",
"tables": {
"chains": {
"name": "chains",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"resource_type": {
"name": "resource_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'chain'"
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"users": {
"name": "users",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"resource_type": {
"name": "resource_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'user'"
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"telegram_chat_id": {
"name": "telegram_chat_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"role": {
"name": "role",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'user'"
}
},
"indexes": {
"users_telegramChatId_unique": {
"name": "users_telegramChatId_unique",
"columns": ["telegram_chat_id"],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}
7 changes: 7 additions & 0 deletions drizzle/meta/_journal.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
"when": 1731512172017,
"tag": "0001_bored_lord_tyger",
"breakpoints": true
},
{
"idx": 2,
"version": "6",
"when": 1731825238968,
"tag": "0002_outgoing_mad_thinker",
"breakpoints": true
}
]
}
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"prepare": "lefthook install"
},
"dependencies": {
"@hono/zod-validator": "^0.4.1",
"drizzle-orm": "^0.36.1",
"drizzle-zod": "^0.5.1",
"grammy": "^1.31.2",
Expand Down
40 changes: 40 additions & 0 deletions scripts/promote-to-admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { inspect, parseArgs } from "node:util";
import { config } from "dotenv";
import { z } from "zod";
import { envSchema } from "../src/shared/context/env.ts";

const argsRaw = parseArgs({
options: {
id: {
type: "string",
},
},
});

const argsSchema = z.object({ id: z.string().uuid() });

const { id } = argsSchema.parse(argsRaw.values);

const env = envSchema.parse(config().parsed);

const response = await fetch(
`http://localhost:5173/admin/users/${id}/promote-to-admin`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
// biome-ignore lint/style/useNamingConvention: env variables have different convention
Authorization: `Basic ${Buffer.from(`${env.ADMIN_USERNAME}:${env.ADMIN_PASSWORD}`).toString("base64")}`,
},
},
);

const body = await response.json();

console.info(
inspect(body, {
depth: Number.POSITIVE_INFINITY,
colors: true,
maxArrayLength: Number.POSITIVE_INFINITY,
}),
);
4 changes: 2 additions & 2 deletions scripts/set-webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Bot } from "grammy";
import { z } from "zod";
import { envSchema } from "../src/shared/context/env.ts";

const rawArgs = parseArgs({
const argsRaw = parseArgs({
options: {
baseUrl: {
type: "string",
Expand All @@ -14,7 +14,7 @@ const rawArgs = parseArgs({

const argsSchema = z.object({ baseUrl: z.string().url() });

export const { baseUrl } = argsSchema.parse(rawArgs.values);
export const { baseUrl } = argsSchema.parse(argsRaw.values);

const env = envSchema.parse(config().parsed);

Expand Down
18 changes: 18 additions & 0 deletions src/api/admin/admin.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Hono } from "hono";
import { basicAuth } from "hono/basic-auth";
import { getContext } from "hono/context-storage";
import type { Context } from "../../shared/context/context.ts";
import { usersRoute } from "./users.route.ts";

export const adminRoute = new Hono();

adminRoute.use((hc, next) => {
const { env } = getContext<Context>().var;

return basicAuth({
username: env.ADMIN_USERNAME,
password: env.ADMIN_PASSWORD,
})(hc, next);
});

adminRoute.route("/users", usersRoute);
28 changes: 28 additions & 0 deletions src/api/admin/users.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { zValidator } from "@hono/zod-validator";
import { Hono } from "hono";
import { z } from "zod";
import { promoteUserToAdmin } from "../../bl/users/users.bl.ts";
import { userSchema } from "../../shared/schema/users.ts";

export const usersRoute = new Hono();

usersRoute.put(
"/:id/promote-to-admin",
zValidator(
"param",
z.object({
id: z.string(),
}),
),
async (hc) => {
const user = await promoteUserToAdmin(hc.req.param("id"));

return hc.json(userDtoSchema.parse(user));
},
);

const userDtoSchema = userSchema.omit({
resourceType: true,
createdAt: true,
updatedAt: true,
});
6 changes: 0 additions & 6 deletions src/api/api/api.route.ts

This file was deleted.

6 changes: 0 additions & 6 deletions src/api/api/chains.route.ts

This file was deleted.

5 changes: 5 additions & 0 deletions src/bl/users/users.bl.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
createUser,
findUserByTelegramChatId,
setUserRole,
} from "../../dal/db/users.table.ts";
import type { User } from "../../shared/schema/users.ts";

Expand All @@ -14,3 +15,7 @@ export async function findOrCreateUserByTelegramChatId(

return await createUser({ telegramChatId });
}

export async function promoteUserToAdmin(id: User["id"]): Promise<User> {
return await setUserRole(id, "admin");
}
33 changes: 28 additions & 5 deletions src/dal/db/users.table.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import { eq } from "drizzle-orm";
import { getContext } from "hono/context-storage";
import { HTTPException } from "hono/http-exception";
import type { Context } from "../../shared/context/context.ts";
import {
type InsertUser,
type CreateUser,
type User,
type UserRole,
createUserSchema,
userRoleSchema,
userSchema,
users,
} from "../../shared/schema/users.ts";

export async function createUser(raw: InsertUser): Promise<User> {
const { db, user } = getContext<Context>().var;
export async function createUser(toCreateRaw: CreateUser): Promise<User> {
const { db } = getContext<Context>().var;

const toCreate = createUserSchema.parse(raw);
const toCreate = createUserSchema.parse(toCreateRaw);

return userSchema.parse(
await db
.insert(users)
.values({ ...toCreate, createdBy: user?.id })
.values({ ...toCreate })
.returning(),
);
}
Expand All @@ -34,3 +37,23 @@ export async function findUserByTelegramChatId(

return raw ? userSchema.parse(raw) : null;
}

export async function setUserRole(
id: User["id"],
toSetRaw: UserRole,
): Promise<User> {
const { db } = getContext<Context>().var;

const toSet = userRoleSchema.parse(toSetRaw);

const [raw] = await db
.update(users)
.set({ role: toSet })
.where(eq(users.id, id))
.returning();
if (!raw) {
throw new HTTPException(404, { message: `User ${id} not found` });
}

return userSchema.parse(raw);
}
Loading

0 comments on commit acf7e43

Please sign in to comment.