Skip to content

Commit

Permalink
Merge branch 'docs_and_status'
Browse files Browse the repository at this point in the history
  • Loading branch information
andreacw5 committed Dec 27, 2023
2 parents d987529 + 3044a05 commit c14a31e
Show file tree
Hide file tree
Showing 8 changed files with 2,029 additions and 1,761 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Andrea Tombolato
Copyright (c) 2024 Andrea Tombolato

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
# Short URL Generator

## Description
This application allows users to create short, personalized URLs using Nest.js.
This application empowers users to generate short, personalized URLs using Nest.js.

## Getting Started
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.
Follow these instructions to set up the project on your local machine for development and testing purposes.
- Clone the repository to your local machine: `git clone https://github.com/andreacw5/short-url-generator.git`
- Install dependencies: `yarn install`
- Start the application: `yarn start:dev`
- Visit `http://localhost:3000` in your browser to use the application.

## Features
- Create short urls
- Edit short urls
- Delete short urls
- Redirect to default url if code is not found
- Click recording for short urls
- Create short URLs
- Edit short URLs
- Delete short URLs
- Redirect to the default URL if the code is not found
- Click recording for short URLs
- Dockerized application
- GitHub actions for build
- API Auth token for CUD endpoints
- API Auth token for create, update, and delete endpoints
- Swagger documentation

## Next planned functionality
- More detailed statistics for short urls
- Testing with Jest
- Deployment with frontend management page

## Built With
Expand All @@ -31,10 +33,10 @@ These instructions will get you a copy of the project up and running on your loc
## Requirements
- [Node.js](https://nodejs.org/en/download/) 18.10.0 or higher
- [Yarn](https://yarnpkg.com/en/) 1.10.1 or higher
- [PostgreSQL](https://www.postgresql.org/download/) 12.0 or higher

## Authentication for management
The authentication is based on single static token, stored on env `API_KEY` variable.
Request for create/edit/delete urls need `X-API-KEY` header with the value of `API_KEY`.
Authentication is based on a single static token stored in the `API_KEY` environment variable. Requests for create/edit/delete URLs require the `X-API-KEY` header with the value of `API_KEY`.

## Environment Variables
| code | description | default value |
Expand All @@ -52,7 +54,7 @@ Request for create/edit/delete urls need `X-API-KEY` header with the value of `A
We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/andreacw5/url-manager-app/releases).

## Author
- [Andrea Tombolato](https://andreacw.dev)
- [Andrea Tombolato](https://andreatombolato.dev)

## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
74 changes: 37 additions & 37 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"name": "url-manager-app",
"version": "1.0.1",
"version": "1.1.0",
"description": "Url manager system with Rest API for management of short urls, click statistics and redirects by personalized codes",
"author": "Andrea Tombolato <andreacw96@gmail.com> (https://github.com/andreacw5)",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/element-gaming/url-shortener"
"url": "https://github.com/andreacw5/url-manager-app"
},
"bugs": {
"url": "https://github.com/element-gaming/url-shortener/issues"
"url": "https://github.com/andreacw5/url-manager-app/issues"
},
"license": "MIT",
"homepage": "https://github.com/element-gaming/url-shortener#readme",
"homepage": "https://github.com/andreacw5/url-manager-app#readme",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
Expand All @@ -29,44 +29,44 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^9.2.1",
"@nestjs/config": "^2.2.0",
"@nestjs/core": "^9.2.1",
"@nestjs/platform-express": "^9.2.1",
"@nestjs/swagger": "^6.1.4",
"@nestjs/passport": "^9.0.0",
"@nestjs/typeorm": "^9.0.1",
"passport": "^0.6.0",
"@nestjs/common": "^10.3.0",
"@nestjs/config": "^3.1.1",
"@nestjs/core": "^10.3.0",
"@nestjs/platform-express": "^10.3.0",
"@nestjs/swagger": "^7.1.17",
"@nestjs/passport": "^9.0.3",
"@nestjs/typeorm": "^10.0.1",
"passport": "^0.7.0",
"passport-headerapikey": "^1.2.2",
"joi": "^17.7.0",
"pg": "^8.9.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^4.1.2",
"rxjs": "^7.8.0",
"typeorm": "^0.3.11"
"joi": "^17.11.0",
"pg": "^8.11.3",
"reflect-metadata": "^0.2.1",
"rimraf": "^5.0.5",
"rxjs": "^7.8.1",
"typeorm": "^0.3.17"
},
"devDependencies": {
"@nestjs/cli": "^9.1.9",
"@nestjs/schematics": "^9.0.4",
"@nestjs/testing": "^9.2.1",
"@types/express": "^4.17.13",
"@types/jest": "29.4.0",
"@types/node": "^18.11.18",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^5.49.0",
"@typescript-eslint/parser": "^5.49.0",
"eslint": "^8.32.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "29.4.1",
"prettier": "^2.8.3",
"@nestjs/cli": "^10.2.1",
"@nestjs/schematics": "^10.0.3",
"@nestjs/testing": "^10.3.0",
"@types/express": "^4.17.21",
"@types/jest": "29.5.11",
"@types/node": "^20.10.5",
"@types/supertest": "^6.0.1",
"@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.2",
"jest": "29.7.0",
"prettier": "^3.1.1",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"ts-jest": "29.0.5",
"ts-loader": "^9.4.2",
"ts-node": "^10.9.1",
"tsconfig-paths": "4.1.2",
"typescript": "^4.9.4"
"ts-jest": "29.1.1",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "4.2.0",
"typescript": "^5.3.3"
},
"jest": {
"moduleFileExtensions": [
Expand Down
5 changes: 3 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ async function bootstrap() {
const appOptions = { cors: true };
const app = await NestFactory.create(AppModule, appOptions);
app.useGlobalFilters(new HttpExceptionFilter());
// app.setGlobalPrefix('api');
const configService = app.get(ConfigService);

// Swagger setup
Expand Down Expand Up @@ -40,4 +39,6 @@ async function bootstrap() {
},
});
}
bootstrap();
bootstrap().then(() => {
Logger.log('App running now!');
});
12 changes: 11 additions & 1 deletion src/modules/app/app.controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Controller, Get, Logger, Param, Res } from '@nestjs/common';
import { UrlsService } from '../url/urls.service';
import { ConfigService } from '@nestjs/config';
import { ApiOperation, ApiParam, ApiResponse } from "@nestjs/swagger";
import { ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger';

@Controller()
export class AppController {
Expand Down Expand Up @@ -43,4 +43,14 @@ export class AppController {
await this.urlsService.updateClickCounter(code);
await res.redirect(url.url);
}

@ApiOperation({ summary: 'Get application status' })
@ApiResponse({ status: 200, description: 'Redirect returned' })
@Get('/api/status')
async appStatus() {
return {
code: 200,
status: 'ok',
};
}
}
25 changes: 22 additions & 3 deletions src/modules/url/urls.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { UrlsService } from './urls.service';
import { Url } from './url.entity';
import {
ApiBasicAuth,
ApiHeaders,
ApiOperation,
ApiResponse,
ApiTags,
Expand All @@ -36,7 +37,7 @@ export class UrlsController {
@Get()
async index(@Query() query): Promise<Url[]> {
this.logger.log(`Request all chats with options: ${JSON.stringify(query)}`);
return await this.urlsService.findAll();
return await this.urlsService.findAll(query);
}

@ApiOperation({ summary: 'Get url by code' })
Expand All @@ -56,6 +57,12 @@ export class UrlsController {
status: 201,
description: 'The url has been successfully created.',
})
@ApiHeaders([
{
name: 'X-API-KEY',
description: 'Auth API key',
},
])
@ApiBasicAuth('api-key')
@UseGuards(AuthGuard('api-key'))
@Post()
Expand All @@ -79,6 +86,12 @@ export class UrlsController {
})
@ApiResponse({ status: 404, description: 'Url not found' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
@ApiHeaders([
{
name: 'X-API-KEY',
description: 'Auth API key',
},
])
@ApiBasicAuth('api-key')
@UseGuards(AuthGuard('api-key'))
@Put('/:id')
Expand All @@ -88,7 +101,7 @@ export class UrlsController {
): Promise<Url> {
this.logger.log(`Request to update url: ${JSON.stringify(updateUrlDTO)}`);
// Check if url exists
const url = await this.urlsService.findOneOrFail({ id });
const url = await this.urlsService.findOne({ id });
if (!url) {
this.logger.log(`Url not found with id: ${id}`);
throw new NotFoundException();
Expand All @@ -106,6 +119,12 @@ export class UrlsController {
status: 201,
description: 'The url has been successfully deleted.',
})
@ApiHeaders([
{
name: 'X-API-KEY',
description: 'Auth API key',
},
])
@ApiResponse({ status: 404, description: 'Url not found' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
@ApiBasicAuth('api-key')
Expand All @@ -114,7 +133,7 @@ export class UrlsController {
async deleteOne(@Param('id') id): Promise<any> {
this.logger.log(`Request to delete url: ${id}`);
// Check if url exists
const url = await this.urlsService.findOneOrFail({ id });
const url = await this.urlsService.findOne({ id });
if (!url) {
this.logger.log(`Url not found with id: ${id}`);
throw new NotFoundException();
Expand Down
4 changes: 2 additions & 2 deletions src/modules/url/urls.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export class UrlsService {
/**
* Find all urls
*/
findAll(): Promise<Url[]> {
return this.urlsRepository.find();
findAll(query): Promise<Url[]> {
return this.urlsRepository.find(query);
}

/**
Expand Down
Loading

0 comments on commit c14a31e

Please sign in to comment.