Add new user patch route

This commit is contained in:
Jesse Wierzbinski 2023-09-13 09:02:16 -10:00
parent b96fe8116e
commit 0bdf559bdc
No known key found for this signature in database
GPG key ID: F9A1E418934E40B0
4 changed files with 180 additions and 0 deletions

View file

@ -0,0 +1,40 @@
import {
Entity,
BaseEntity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
ManyToOne,
} from "typeorm";
import { User } from "./User";
import { Application } from "./Application";
export enum TokenType {
BEARER = "bearer",
}
@Entity({
name: "tokens",
})
export class Token extends BaseEntity {
@PrimaryGeneratedColumn("uuid")
id!: string;
@Column("varchar")
token_type!: TokenType;
@Column("varchar")
scope!: string;
@Column("varchar")
access_token!: string;
@CreateDateColumn()
created_at!: Date;
@ManyToOne(() => User, user => user.id)
user!: User;
@ManyToOne(() => Application, application => application.id)
application!: Application;
}

View file

@ -0,0 +1,125 @@
import { getUserByToken } from "@auth";
import { getConfig } from "@config";
import { errorResponse, jsonResponse } from "@response";
/**
* Patches a user
*/
export default async (req: Request): Promise<Response> => {
// Check if request is a PATCH request
if (req.method !== "PATCH")
return errorResponse("This method requires a PATCH request", 405);
// Check auth token
const token = req.headers.get("Authorization")?.split(" ")[1] || null;
if (!token)
return errorResponse("This method requires an authenticated user", 422);
const user = await getUserByToken(token);
if (!user) return errorResponse("Unauthorized", 401);
const config = getConfig();
const body = await req.formData();
const display_name = body.get("display_name")?.toString() || null;
const note = body.get("note")?.toString() || null;
// Avatar is a file element
const avatar = (body.get("avatar") as File | null) || null;
const header = (body.get("header") as File | null) || null;
const locked = body.get("locked")?.toString() || null;
const bot = body.get("bot")?.toString() || null;
const discoverable = body.get("discoverable")?.toString() || null;
// TODO: Implement other options like field or source
// const source_privacy = body.get("source[privacy]")?.toString() || null;
// const source_sensitive = body.get("source[sensitive]")?.toString() || null;
// const source_language = body.get("source[language]")?.toString() || null;
if (display_name) {
// Check if within allowed display name lengths
if (
display_name.length < 3 ||
display_name.length > config.validation.max_displayname_size
) {
return errorResponse(
`Display name must be between 3 and ${config.validation.max_displayname_size} characters`,
422
);
}
user.display_name = display_name;
}
if (note) {
// Check if within allowed note length
if (note.length > config.validation.max_note_size) {
return errorResponse(
`Note must be less than ${config.validation.max_note_size} characters`,
422
);
}
user.bio = note;
}
if (avatar) {
// Check if within allowed avatar length (avatar is an image)
if (avatar.size > config.validation.max_avatar_size) {
return errorResponse(
`Avatar must be less than ${config.validation.max_avatar_size} bytes`,
422
);
}
// TODO: Store the file somewhere and then change the user's actual avatar
}
if (header) {
// Check if within allowed header length (header is an image)
if (header.size > config.validation.max_header_size) {
return errorResponse(
`Header must be less than ${config.validation.max_avatar_size} bytes`,
422
);
}
// TODO: Store the file somewhere and then change the user's actual header
}
if (locked) {
// Check if locked is a boolean
if (locked !== "true" && locked !== "false") {
return errorResponse("Locked must be a boolean", 422);
}
// TODO: Add a user value for Locked
// user.locked = locked === "true";
}
if (bot) {
// Check if bot is a boolean
if (bot !== "true" && bot !== "false") {
return errorResponse("Bot must be a boolean", 422);
}
// TODO: Add a user value for bot
// user.bot = bot === "true";
}
if (discoverable) {
// Check if discoverable is a boolean
if (discoverable !== "true" && discoverable !== "false") {
return errorResponse("Discoverable must be a boolean", 422);
}
// TODO: Add a user value for discoverable
// user.discoverable = discoverable === "true";
}
return jsonResponse(
{
error: `Not really implemented yet`,
},
501
);
};

13
utils/auth.ts Normal file
View file

@ -0,0 +1,13 @@
import { Token } from "~database/entities/Token";
export const getUserByToken = async (access_token: string | null) => {
if (!access_token) return null;
const token = await Token.findOneBy({
access_token,
});
if (!token) return null;
return token.user;
};

View file

@ -17,6 +17,8 @@ export interface ConfigType {
max_bio_size: number;
max_username_size: number;
max_note_size: number;
max_avatar_size: number;
max_header_size: number;
max_media_size: number;
max_media_attachments: number;
max_media_description_size: number;