mirror of
https://github.com/diced/zipline.git
synced 2026-01-08 03:11:24 -08:00
url shortener api
This commit is contained in:
@@ -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.');
|
||||
|
||||
87
src/controllers/URLSController.ts
Normal file
87
src/controllers/URLSController.ts
Normal 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
27
src/entities/URL.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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, {
|
||||
|
||||
Reference in New Issue
Block a user