url shortener api

This commit is contained in:
dicedtomato
2020-10-12 21:30:21 +00:00
committed by GitHub
parent 75f8bc38c8
commit fa6e7e9ca9
4 changed files with 138 additions and 1 deletions

View File

@@ -11,6 +11,7 @@ import { createWriteStream, existsSync, mkdirSync } from 'fs';
import { join } from 'path';
import { Repository } from 'typeorm';
import { Image } from '../entities/Image';
import { URL } from '../entities/URL';
import { User } from '../entities/User';
import { AuthError } from '../lib/api/APIErrors';
import { Configuration } from '../lib/Config';
@@ -26,12 +27,33 @@ export class RootController {
private users: Repository<User> = this.instance.orm.getRepository(User);
private images: Repository<Image> = this.instance.orm.getRepository(Image);
private urls: Repository<URL> = this.instance.orm.getRepository(URL);
@GET('/config/uploader')
async uploaderConfig() {
return Configuration.readConfig().uploader;
}
@GET('/s/:id')
async getShorten(req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
const urlId = await this.urls.findOne({
where: {
id: req.params.id
}
});
const urlVanity = await this.urls.findOne({
where: {
vanity: req.params.id
}
});
if (urlVanity) return reply.redirect(urlVanity.url);
if (!urlId) reply.send('Not found');
return reply.redirect(urlId.url);
}
@GET('/users')
async allUsers(req: FastifyRequest, reply: FastifyReply) {
if (!req.cookies.zipline) throw new Error('Not logged in.');

View File

@@ -0,0 +1,87 @@
import { FastifyReply, FastifyRequest, FastifyInstance } from 'fastify';
import {
Controller,
FastifyInstanceToken,
Inject,
GET,
DELETE,
POST
} from 'fastify-decorators';
import { Repository } from 'typeorm';
import { URL } from '../entities/URL';
import { User } from '../entities/User';
import { LoginError } from '../lib/api/APIErrors';
import { Configuration } from '../lib/Config';
import { createRandomId, readBaseCookie } from '../lib/Encryption';
const config = Configuration.readConfig();
if (!config) process.exit(0);
@Controller('/api/urls')
export class URLSController {
@Inject(FastifyInstanceToken)
private instance!: FastifyInstance;
private urls: Repository<URL> = this.instance.orm.getRepository(URL);
private users: Repository<User> = this.instance.orm.getRepository(User);
@GET('/')
async allURLS(req: FastifyRequest, reply: FastifyReply) {
if (!req.cookies.zipline) throw new LoginError('Not logged in.');
const all = await this.urls.find({
where: {
user: readBaseCookie(req.cookies.zipline),
},
});
return reply.send(all);
}
@DELETE('/:id')
async deleteURL(req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) {
if (!req.cookies.zipline) throw new LoginError('Not logged in.');
const url = await this.urls.findOne({
where: {
user: readBaseCookie(req.cookies.zipline),
id: req.params.id
}
});
if (!url) throw new Error('No url');
this.urls.delete({
id: req.params.id
});
return reply.send(url);
}
@POST('/')
async createURL(req: FastifyRequest<{ Body: { vanity: string, url: string } }>, reply: FastifyReply) {
if (!req.cookies.zipline) throw new LoginError('Not logged in.');
if (req.body.vanity) {
const existingVanity = await this.urls.findOne({
where: {
vanity: req.body.vanity
}
});
if (existingVanity) throw new Error('There is an existing vanity!');
}
const user = await this.users.findOne({
where: {
id: readBaseCookie(req.cookies.zipline)
}
});
if (!user) throw new LoginError('No user');
const url = await this.urls.save(
new URL(createRandomId(4), user.id, req.body.url, req.body.vanity || null)
)
return reply.send(url);
}
}

27
src/entities/URL.ts Normal file
View File

@@ -0,0 +1,27 @@
import { Entity, Column, PrimaryColumn } from 'typeorm';
@Entity({ name: 'zipline_urls' })
export class URL {
@PrimaryColumn('text')
public id: string;
@Column('text', { default: null })
public url: string;
@Column('text', { default: null, nullable: true })
public vanity: string;
@Column('bigint')
public user: number;
@Column('bigint', { default: 0 })
public clicks: 0;
public constructor(id: string, user: number, url: string, vanity: string = null) {
this.id = id;
this.user = user;
this.url = url;
this.vanity = vanity;
this.clicks = 0;
}
}

View File

@@ -15,6 +15,7 @@ import { UserController } from './controllers/UserController';
import { RootController } from './controllers/RootController';
import { join } from 'path';
import { ImagesController } from './controllers/ImagesController';
import { URLSController } from './controllers/URLSController';
Console.setFormatter(new ConsoleFormatter());
@@ -55,7 +56,7 @@ server.register(fastifyTypeorm, {
});
server.register(bootstrap, {
controllers: [UserController, RootController, ImagesController],
controllers: [UserController, RootController, ImagesController, URLSController],
});
server.register(fastifyCookies, {