mirror of
https://github.com/OneUptime/oneuptime
synced 2024-11-22 23:30:10 +00:00
add url shortner
This commit is contained in:
parent
d724932660
commit
f18bb3a3de
45
CommonServer/Services/ShortLinkService.ts
Normal file
45
CommonServer/Services/ShortLinkService.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
|
||||
import Model from 'Model/Models/ShortLink';
|
||||
import DatabaseService, { OnCreate } from './DatabaseService';
|
||||
import CreateBy from '../Types/Database/CreateBy';
|
||||
import Text from 'Common/Types/Text';
|
||||
import URL from 'Common/Types/API/URL';
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
super(Model, postgresDatabase);
|
||||
this.hardDeleteItemsOlderThanInDays("createdAt", 3); //expire links in 3 days.
|
||||
}
|
||||
|
||||
protected override async onBeforeCreate(
|
||||
createBy: CreateBy<Model>
|
||||
): Promise<OnCreate<Model>> {
|
||||
|
||||
createBy.data.shortId = Text.generateRandomText(8);
|
||||
|
||||
return { createBy: createBy, carryForward: [] };
|
||||
}
|
||||
|
||||
public async saveShortLinkFor(url: URL): Promise<Model> {
|
||||
const model: Model = new Model();
|
||||
model.link = url;
|
||||
return await this.create({ data: model, props: { isRoot: true } });
|
||||
}
|
||||
|
||||
public async getShortLinkFor(shortLinkId: string): Promise<Model | null> {
|
||||
return await this.findOneBy({
|
||||
query: {
|
||||
shortId: shortLinkId,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
link: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
32
LinkShortner/API/LinkShortner.ts
Normal file
32
LinkShortner/API/LinkShortner.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import Express, {
|
||||
ExpressRequest,
|
||||
ExpressResponse,
|
||||
ExpressRouter,
|
||||
} from 'CommonServer/Utils/Express';
|
||||
import Response from 'CommonServer/Utils/Response';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import ShortLinkService from 'CommonServer/Services/ShortLinkService';
|
||||
import ShortLink from 'Model/Models/ShortLink';
|
||||
|
||||
const router: ExpressRouter = Express.getRouter();
|
||||
|
||||
|
||||
router.get(
|
||||
'/:id',
|
||||
async (req: ExpressRequest, res: ExpressResponse) => {
|
||||
|
||||
if(!req.params['id']){
|
||||
return Response.sendErrorResponse(req, res, new BadDataException("id is required"));
|
||||
}
|
||||
|
||||
const link: ShortLink | null = await ShortLinkService.getShortLinkFor(
|
||||
req.params['id']
|
||||
);
|
||||
|
||||
if (!link || !link.link) {
|
||||
return Response.sendErrorResponse(req, res, new BadDataException("This URL is invalid or expired"));
|
||||
}
|
||||
|
||||
return Response.redirect(req, res, link.link);
|
||||
}
|
||||
);
|
@ -5,9 +5,11 @@ import App from 'CommonServer/Utils/StartServer';
|
||||
import { PostgresAppInstance } from 'CommonServer/Infrastructure/PostgresDatabase';
|
||||
import logger from 'CommonServer/Utils/Logger';
|
||||
|
||||
|
||||
const APP_NAME: string = 'l';
|
||||
|
||||
|
||||
app.use([`/${APP_NAME}/`, '/'], LinkShortnerAPI);
|
||||
|
||||
const app: ExpressApplication = Express.getExpressApp();
|
||||
|
||||
const init: Function = async (): Promise<void> => {
|
||||
|
80
Model/Models/ShortLink.ts
Normal file
80
Model/Models/ShortLink.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import { Column, Entity, Index } from 'typeorm';
|
||||
import BaseModel from 'Common/Models/BaseModel';
|
||||
import CrudApiEndpoint from 'Common/Types/Database/CrudApiEndpoint';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import TableColumnType from 'Common/Types/Database/TableColumnType';
|
||||
import TableColumn from 'Common/Types/Database/TableColumn';
|
||||
import ColumnType from 'Common/Types/Database/ColumnType';
|
||||
import ColumnLength from 'Common/Types/Database/ColumnLength';
|
||||
import TableAccessControl from 'Common/Types/Database/AccessControl/TableAccessControl';
|
||||
import ColumnAccessControl from 'Common/Types/Database/AccessControl/ColumnAccessControl';
|
||||
import TableMetadata from 'Common/Types/Database/TableMetadata';
|
||||
import IconProp from 'Common/Types/Icon/IconProp';
|
||||
import URL from 'Common/Types/API/URL';
|
||||
|
||||
@TableAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
|
||||
],
|
||||
delete: [],
|
||||
update: [],
|
||||
})
|
||||
@CrudApiEndpoint(new Route('/short-link'))
|
||||
@Entity({
|
||||
name: 'ShortLink',
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: 'ShortLink',
|
||||
singularName: 'Short Link',
|
||||
pluralName: 'Short Links',
|
||||
icon: IconProp.Link,
|
||||
tableDescription:
|
||||
'Short links are used to redirect users to a specific long link in OneUptime.',
|
||||
})
|
||||
export default class SmsLog extends BaseModel {
|
||||
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.ShortText,
|
||||
title: 'Short Link ID',
|
||||
description: 'Random ID for the short link',
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public shortId?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.LongURL,
|
||||
title: 'Long URL',
|
||||
description: 'Long URL to redirect to',
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.LongURL,
|
||||
transformer: URL.getDatabaseTransformer(),
|
||||
})
|
||||
public link?: URL = undefined;
|
||||
}
|
Loading…
Reference in New Issue
Block a user