# Реалізація інформаційного та програмного забезпечення
# SQL-скрипт
-- MySQL Script generated by MySQL Workbench
-- Wed Apr 26 17:39:47 2023
-- Model: New Model Version: 1.0
-- MySQL Workbench Forward Engineering
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
DROP SCHEMA IF EXISTS `mydb` ;
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`roles`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`roles` ;
CREATE TABLE IF NOT EXISTS `mydb`.`roles` (
`id` INT NOT NULL,
`name` VARCHAR(45) NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`users`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`users` ;
CREATE TABLE `mydb`.`users` (
`id` INT NOT NULL AUTO_INCREMENT,
`user_name` TEXT NOT NULL,
`email` VARCHAR(45) NOT NULL,
`password` TEXT NOT NULL,
`role_id` INT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE INDEX `idx_email` (`email` ASC) VISIBLE,
INDEX `fk_roles_users_idx` (`role_id` ASC) VISIBLE,
CONSTRAINT `fk_roles_users`
FOREIGN KEY (`role_id`)
REFERENCES `mydb`.`roles` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`studies`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`studies` ;
CREATE TABLE IF NOT EXISTS `mydb`.`studies` (
`id` INT NOT NULL AUTO_INCREMENT,
`authors` INT NULL,
`engagement` INT NULL,
`mentions` INT NULL,
`status` ENUM("Pending", "Grabbing", "Canceled", "Done") NOT NULL,
`owner_id` INT NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_owner_id` (`owner_id` ASC) VISIBLE,
CONSTRAINT `fk_studies_users`
FOREIGN KEY (`owner_id`)
REFERENCES `mydb`.`users` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`posts`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`posts` ;
CREATE TABLE IF NOT EXISTS `mydb`.`posts` (
`id` INT NOT NULL AUTO_INCREMENT,
`url` TEXT NOT NULL,
`date_of_publication` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`tonality` FLOAT NOT NULL,
`weight` FLOAT NOT NULL,
`refers_to` INT NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_refers_to` (`refers_to` ASC) VISIBLE,
CONSTRAINT `fk_posts_studies`
FOREIGN KEY (`refers_to`)
REFERENCES `mydb`.`studies` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`authors`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`authors` ;
CREATE TABLE IF NOT EXISTS `mydb`.`authors` (
`id` INT NOT NULL AUTO_INCREMENT,
`sex` INT NULL,
`geolocation` TEXT NULL,
`age` INT NULL,
`refers_to` INT NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_refers_to` (`refers_to` ASC) VISIBLE,
CONSTRAINT `fk_authors_studies`
FOREIGN KEY (`refers_to`)
REFERENCES `mydb`.`studies` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
# RESTfull сервіс для управління даними
entity/User.ts
import { Entity, BaseEntity, Column, PrimaryGeneratedColumn, Unique } from "typeorm";
@Entity("users")
@Unique(["email"])
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
email: string;
@Column()
password: string;
@Column()
userName: string;
@Column()
roleId: number;
}
controller/UserController.ts
import { Database } from "../database";
import { Repository, QueryFailedError, EntityNotFoundError } from "typeorm";
import { User } from "../entity/User";
import { Request, Response } from "express";
type Handler = (req: Request, res: Response) => Promise<void>;
export class UserController {
private repository: Repository<User>;
constructor(database: Database) {
this.repository = database.getRepository(User);
}
errorHandler = (e: Error, res: Response) => {
switch (e.constructor) {
case EntityNotFoundError:
res.status(404).json({
errorMessage: "Not Found",
});
break;
case QueryFailedError:
res.status(400).json({
errorMessage: "Bad request",
});
break;
default:
res.status(500).send({
errorMessage: "An unknown error",
});
break;
}
}
find: Handler = async (_, res) => {
const users = await this.repository.find();
res.json(users);
}
findOne: Handler = async (req, res) => {
try {
const user = await this.repository.findOneBy({
id: Number(req.params.id),
});
if (user === null) {
throw new EntityNotFoundError(User, null);
}
res.json(user);
} catch (e) {
this.errorHandler(e, res);
}
}
create: Handler = async (req, res) => {
try {
const user = this.repository.create(req.body);
const results = await this.repository.save(user);
res.json(results);
} catch (e) {
this.errorHandler(e, res);
}
}
remove: Handler = async (req, res) => {
try {
const { id } = req.params;
await this.repository.delete(id);
res.json({
message: `A user with id ${id} was removed`,
});
} catch (e) {
this.errorHandler(e, res);
}
}
update: Handler = async (req, res) => {
try {
const user = await this.repository.findOneBy({
id: Number(req.params.id),
});
this.repository.merge(user, req.body);
const results = await this.repository.save(user);
res.send(results);
} catch (e) {
this.errorHandler(e, res);
}
}
}
database.ts
import { DataSource, EntityTarget } from "typeorm";
import { SnakeNamingStrategy } from "typeorm-naming-strategies";
import { User } from "./entity/User";
export class Database {
private origin: DataSource;
constructor() {
this.origin = new DataSource({
type: "mysql",
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
entities: [User],
namingStrategy: new SnakeNamingStrategy(),
});
}
async connect() {
return await this.origin.initialize();
}
getRepository<T>(repositoryClass: EntityTarget<T>) {
return this.origin.getRepository(repositoryClass);
}
}
index.ts
require("dotenv").config();
import "reflect-metadata";
import * as express from "express";
import { Database } from "./database";
import { UserController } from "./controller/UserController";
(async () => {
const db = new Database();
await db.connect();
const userController = new UserController(db);
const app = express();
app.use(express.json());
app
.route("/users")
.get(userController.find)
.post(userController.create);
app
.route("/users/:id")
.get(userController.findOne)
.delete(userController.remove)
.put(userController.update);
app.listen(80);
})();