migrate to ci and postgress
This commit is contained in:
@ -1,31 +1,34 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { DB_STORAGES, DB_USERS, MONGO_URL } from './consts';
|
||||
import {
|
||||
StorageDocument,
|
||||
StorageScheme,
|
||||
UserDocument,
|
||||
UserScheme,
|
||||
} from './schemas';
|
||||
import { UserEntity } from './entities/user.entity';
|
||||
import { StorageEntity } from './entities/storage.entity';
|
||||
import { HealthModule } from './health/health.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
MongooseModule.forRoot(`${MONGO_URL}/${DB_USERS}`, {
|
||||
connectionName: DB_USERS,
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
envFilePath: ['.env.local', '.env'],
|
||||
}),
|
||||
MongooseModule.forRoot(`${MONGO_URL}/${DB_STORAGES}`, {
|
||||
connectionName: DB_STORAGES,
|
||||
TypeOrmModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
inject: [ConfigService],
|
||||
useFactory: (configService: ConfigService) => ({
|
||||
type: 'postgres',
|
||||
host: configService.get('DATABASE_HOST', 'localhost'),
|
||||
port: configService.get('DATABASE_PORT', 5432),
|
||||
username: configService.get('DATABASE_USER', 'postgres'),
|
||||
password: configService.get('DATABASE_PASSWORD', 'postgres'),
|
||||
database: configService.get('DATABASE_NAME', 'simple_storage_db'),
|
||||
entities: [UserEntity, StorageEntity],
|
||||
synchronize: true,
|
||||
}),
|
||||
}),
|
||||
MongooseModule.forFeature(
|
||||
[{ name: UserDocument.name, schema: UserScheme }],
|
||||
DB_USERS,
|
||||
),
|
||||
MongooseModule.forFeature(
|
||||
[{ name: StorageDocument.name, schema: StorageScheme }],
|
||||
DB_STORAGES,
|
||||
),
|
||||
TypeOrmModule.forFeature([UserEntity, StorageEntity]),
|
||||
HealthModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
|
||||
@ -3,9 +3,11 @@ import {
|
||||
Injectable,
|
||||
NotAcceptableException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { StorageDocument, UserDocument } from './schemas';
|
||||
import { Model } from 'mongoose';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
import { UserEntity } from './entities/user.entity';
|
||||
import { StorageEntity } from './entities/storage.entity';
|
||||
import {
|
||||
User,
|
||||
Storage,
|
||||
@ -13,21 +15,18 @@ import {
|
||||
StorageUpdate,
|
||||
StorageList,
|
||||
} from './types';
|
||||
import { v4 } from 'uuid';
|
||||
import { DB_STORAGES, DB_USERS } from './consts';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
constructor(
|
||||
@InjectModel(UserDocument.name, DB_USERS)
|
||||
private userModel: Model<UserDocument>,
|
||||
@InjectModel(StorageDocument.name, DB_STORAGES)
|
||||
private storageModel: Model<StorageDocument>,
|
||||
@InjectRepository(UserEntity)
|
||||
private userRepository: Repository<UserEntity>,
|
||||
@InjectRepository(StorageEntity)
|
||||
private storageRepository: Repository<StorageEntity>,
|
||||
) {}
|
||||
|
||||
async checkRequest(token?: string): Promise<User> {
|
||||
const userList = await this.userModel.find().exec();
|
||||
const searchUser = userList.find((user) => user.token === token);
|
||||
const searchUser = await this.userRepository.findOne({ where: { token } });
|
||||
if (searchUser) {
|
||||
return {
|
||||
login: searchUser.login,
|
||||
@ -38,37 +37,36 @@ export class AppService {
|
||||
}
|
||||
|
||||
async authUser(login: string): Promise<string> {
|
||||
const userList = await this.userModel.find().exec();
|
||||
const searchUser = userList.find((user) => user.login === login);
|
||||
const searchUser = await this.userRepository.findOne({ where: { login } });
|
||||
if (searchUser) {
|
||||
return searchUser.token;
|
||||
}
|
||||
const Model = this.userModel;
|
||||
const userModel = new Model({
|
||||
const newUser = await this.userRepository.save({
|
||||
login,
|
||||
token: v4(),
|
||||
});
|
||||
const newUser = await userModel.save();
|
||||
return newUser.token;
|
||||
}
|
||||
|
||||
async getStorageList(login: string): Promise<StorageList> {
|
||||
const storageList = await this.storageModel.find().exec();
|
||||
const preparedList = storageList.map(({ _id, user, storageName }) => ({
|
||||
id: _id as string,
|
||||
const storageList = await this.storageRepository.find({
|
||||
where: { user: login },
|
||||
});
|
||||
return storageList.map(({ id, user, storageName }) => ({
|
||||
id,
|
||||
user,
|
||||
storageName,
|
||||
}));
|
||||
|
||||
return preparedList.filter(({ user }) => user === login);
|
||||
}
|
||||
|
||||
async getStorageById(login: string, id: string): Promise<Storage> {
|
||||
const searchStorage = await this.storageModel.findById(id);
|
||||
const searchStorage = await this.storageRepository.findOne({
|
||||
where: { id },
|
||||
});
|
||||
if (searchStorage && searchStorage.user === login) {
|
||||
return {
|
||||
data: searchStorage.data,
|
||||
id: searchStorage._id as string,
|
||||
id: searchStorage.id,
|
||||
storageName: searchStorage.storageName,
|
||||
user: searchStorage.user,
|
||||
};
|
||||
@ -77,25 +75,19 @@ export class AppService {
|
||||
}
|
||||
|
||||
async addStorage(login: string, storage: StorageCreate): Promise<Storage> {
|
||||
const Model = this.storageModel;
|
||||
const storageModel = new Model({
|
||||
if (!storage.data || !storage.storageName) {
|
||||
throw new BadRequestException('data и storageName обязательны');
|
||||
}
|
||||
const newStorage = await this.storageRepository.save({
|
||||
data: storage.data,
|
||||
storageName: storage.storageName,
|
||||
user: login,
|
||||
});
|
||||
try {
|
||||
await storageModel.validate();
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
throw new BadRequestException(e.message);
|
||||
}
|
||||
|
||||
const newStorage = await storageModel.save();
|
||||
return {
|
||||
data: newStorage.data,
|
||||
user: newStorage.user,
|
||||
storageName: newStorage.storageName,
|
||||
id: newStorage._id as string,
|
||||
id: newStorage.id,
|
||||
};
|
||||
}
|
||||
|
||||
@ -104,7 +96,9 @@ export class AppService {
|
||||
id: string,
|
||||
storage: StorageUpdate,
|
||||
): Promise<Storage> {
|
||||
const searchStorage = await this.storageModel.findById(id);
|
||||
const searchStorage = await this.storageRepository.findOne({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
if (!searchStorage || searchStorage.user !== login) {
|
||||
throw new BadRequestException(`Storage с id - "${id}" не найден`);
|
||||
@ -112,7 +106,7 @@ export class AppService {
|
||||
|
||||
const updatedStorageName = storage.storageName ?? searchStorage.storageName;
|
||||
|
||||
await searchStorage.updateOne({
|
||||
await this.storageRepository.update(id, {
|
||||
data: storage.data,
|
||||
storageName: updatedStorageName,
|
||||
});
|
||||
@ -121,24 +115,25 @@ export class AppService {
|
||||
data: storage.data,
|
||||
user: searchStorage.user,
|
||||
storageName: updatedStorageName,
|
||||
id: searchStorage._id as string,
|
||||
id: searchStorage.id,
|
||||
};
|
||||
}
|
||||
|
||||
async deleteStorageById(login: string, id: string): Promise<Storage> {
|
||||
const searchStorage = await this.storageModel.findById(id);
|
||||
const searchStorage = await this.storageRepository.findOne({
|
||||
where: { id },
|
||||
});
|
||||
if (!searchStorage || searchStorage.user !== login) {
|
||||
throw new BadRequestException(`Storage с id - "${id}" не найден`);
|
||||
}
|
||||
const Model = this.storageModel;
|
||||
|
||||
await Model.findByIdAndDelete(id);
|
||||
await this.storageRepository.delete(id);
|
||||
|
||||
return {
|
||||
data: searchStorage.data,
|
||||
user: searchStorage.user,
|
||||
storageName: searchStorage.storageName,
|
||||
id: searchStorage._id as string,
|
||||
id: searchStorage.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,3 @@
|
||||
// Подключение к MongoDB
|
||||
export const MONGO_URL = process.env.MONGODB_URI || 'mongodb://localhost:27017';
|
||||
|
||||
// Имя базы данных для пользователей и хранилищ
|
||||
export const DB_USERS = process.env.DB_USERS || 'storage-back-users';
|
||||
export const DB_STORAGES = process.env.DB_STORAGES || 'storage-back-storages';
|
||||
|
||||
// Порт приложения
|
||||
export const APP_PORT = parseInt(process.env.APP_PORT || '3000', 10);
|
||||
|
||||
|
||||
16
src/entities/storage.entity.ts
Normal file
16
src/entities/storage.entity.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
|
||||
|
||||
@Entity('storages')
|
||||
export class StorageEntity {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ type: 'jsonb' })
|
||||
data: object;
|
||||
|
||||
@Column({ type: 'varchar' })
|
||||
storageName: string;
|
||||
|
||||
@Column({ type: 'varchar' })
|
||||
user: string;
|
||||
}
|
||||
13
src/entities/user.entity.ts
Normal file
13
src/entities/user.entity.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
|
||||
|
||||
@Entity('users')
|
||||
export class UserEntity {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ type: 'varchar', unique: true })
|
||||
login: string;
|
||||
|
||||
@Column({ type: 'varchar' })
|
||||
token: string;
|
||||
}
|
||||
20
src/health/health.controller.ts
Normal file
20
src/health/health.controller.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import {
|
||||
HealthCheckService,
|
||||
HealthCheck,
|
||||
TypeOrmHealthIndicator,
|
||||
} from '@nestjs/terminus';
|
||||
|
||||
@Controller('health')
|
||||
export class HealthController {
|
||||
constructor(
|
||||
private health: HealthCheckService,
|
||||
private db: TypeOrmHealthIndicator,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@HealthCheck()
|
||||
check() {
|
||||
return this.health.check([() => this.db.pingCheck('database')]);
|
||||
}
|
||||
}
|
||||
9
src/health/health.module.ts
Normal file
9
src/health/health.module.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TerminusModule } from '@nestjs/terminus';
|
||||
import { HealthController } from './health.controller';
|
||||
|
||||
@Module({
|
||||
imports: [TerminusModule],
|
||||
controllers: [HealthController],
|
||||
})
|
||||
export class HealthModule {}
|
||||
@ -1,6 +1,4 @@
|
||||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Document } from 'mongoose';
|
||||
import { Storage, StorageCreate } from './types';
|
||||
|
||||
export class AuthRequest {
|
||||
@ -8,45 +6,6 @@ export class AuthRequest {
|
||||
login: string;
|
||||
}
|
||||
|
||||
@Schema()
|
||||
export class UserDocument extends Document {
|
||||
@Prop({
|
||||
type: String,
|
||||
required: true,
|
||||
})
|
||||
login: string;
|
||||
|
||||
@Prop({
|
||||
type: String,
|
||||
required: true,
|
||||
})
|
||||
token: string;
|
||||
}
|
||||
|
||||
@Schema()
|
||||
export class StorageDocument extends Document {
|
||||
@Prop({
|
||||
type: Object,
|
||||
required: true,
|
||||
})
|
||||
data: object;
|
||||
|
||||
@Prop({
|
||||
type: String,
|
||||
required: true,
|
||||
})
|
||||
storageName: string;
|
||||
|
||||
@Prop({
|
||||
type: String,
|
||||
required: true,
|
||||
})
|
||||
user: string;
|
||||
}
|
||||
|
||||
export const StorageScheme = SchemaFactory.createForClass(StorageDocument);
|
||||
export const UserScheme = SchemaFactory.createForClass(UserDocument);
|
||||
|
||||
export class StorageResponse implements Storage {
|
||||
@ApiProperty()
|
||||
data: object;
|
||||
|
||||
Reference in New Issue
Block a user