diff --git a/backend/resources/scripts/ubuntu@dailyroad.site/elasticsearch/log_index_template.json b/backend/resources/scripts/ubuntu@dailyroad.site/elasticsearch/log_index_template.json deleted file mode 100644 index 519f124e..00000000 --- a/backend/resources/scripts/ubuntu@dailyroad.site/elasticsearch/log_index_template.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "index_patterns": [ - "dailyroad-*" - ], - "template": { - "settings": { - "number_of_shards": 1, - "number_of_replicas": 1 - }, - "mappings": { - "properties": { - "@timestamp": { - "type": "date" - }, - "log_level": { - "type": "keyword" - }, - "log_message": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "req": { - "properties": { - "id": { - "type": "integer" - }, - "method": { - "type": "keyword" - }, - "url": { - "type": "keyword" - }, - "headers": { - "type": "object", - "enabled": false - } - } - } - } - } - } -} diff --git a/backend/resources/scripts/ubuntu@dailyroad.site/kibana/level.painless b/backend/resources/scripts/ubuntu@dailyroad.site/kibana/level.painless deleted file mode 100644 index 09217398..00000000 --- a/backend/resources/scripts/ubuntu@dailyroad.site/kibana/level.painless +++ /dev/null @@ -1,26 +0,0 @@ -if (!params['_source'].containsKey('message')) { - emit("no message"); - return; -} - -String message = params['_source']['message']; -if (message == null) { - emit("message is null"); - return; -} - -// "level":" 를 기준으로 값 추출 -int startIndex = message.indexOf('"level":"'); -if (startIndex == -1) { - emit("no msg in message"); - return; -} - -startIndex += 9; // "level":"의 길이만큼 이동 -int endIndex = message.indexOf('"', startIndex); -if (endIndex == -1) { - emit("no end of msg"); - return; -} - -emit(message.substring(startIndex, endIndex)); diff --git a/backend/resources/scripts/ubuntu@dailyroad.site/kibana/log-message.painless b/backend/resources/scripts/ubuntu@dailyroad.site/kibana/log-message.painless deleted file mode 100644 index 824f65dc..00000000 --- a/backend/resources/scripts/ubuntu@dailyroad.site/kibana/log-message.painless +++ /dev/null @@ -1,26 +0,0 @@ -if (!params['_source'].containsKey('message')) { - emit("no message"); - return; -} - -String message = params['_source']['message']; -if (message == null) { - emit("message is null"); - return; -} - -// "msg":" 를 기준으로 값 추출 -int startIndex = message.indexOf('"msg":"'); -if (startIndex == -1) { - emit("no msg in message"); - return; -} - -startIndex += 7; // "msg":"의 길이만큼 이동 -int endIndex = message.indexOf('"', startIndex); -if (endIndex == -1) { - emit("no end of msg"); - return; -} - -emit(message.substring(startIndex, endIndex)); diff --git a/backend/resources/scripts/ubuntu@dailyroad.site/kibana/request.painless b/backend/resources/scripts/ubuntu@dailyroad.site/kibana/request.painless deleted file mode 100644 index bb2dfcf9..00000000 --- a/backend/resources/scripts/ubuntu@dailyroad.site/kibana/request.painless +++ /dev/null @@ -1,46 +0,0 @@ -if (!params['_source'].containsKey('message')) { - emit("no message"); - return; -} - -String message = params['_source']['message']; -if (message == null) { - emit("message is null"); - return; -} - -// "method":" 를 기준으로 method 값 추출 -int methodStartIndex = message.indexOf('"method":"'); -if (methodStartIndex == -1) { - emit("no method in message"); - return; -} - -methodStartIndex += 10; // "method":"의 길이만큼 이동 -int methodEndIndex = message.indexOf('"', methodStartIndex); -if (methodEndIndex == -1) { - emit("no end of method"); - return; -} - -String method = message.substring(methodStartIndex, methodEndIndex); - -// "url":" 를 기준으로 url 값 추출 -int urlStartIndex = message.indexOf('"url":"'); -if (urlStartIndex == -1) { - emit("no url in message"); - return; -} - -urlStartIndex += 7; // "url":"의 길이만큼 이동 -int urlEndIndex = message.indexOf('"', urlStartIndex); -if (urlEndIndex == -1) { - emit("no end of url"); - return; -} - -String url = message.substring(urlStartIndex, urlEndIndex); - -// method와 url을 합쳐 request 생성 -String request = method + " " + url; -emit(request); diff --git a/backend/resources/scripts/ubuntu@dailyroad.site/logstash/logstash.conf b/backend/resources/scripts/ubuntu@dailyroad.site/logstash/logstash.conf deleted file mode 100644 index d16ffdd9..00000000 --- a/backend/resources/scripts/ubuntu@dailyroad.site/logstash/logstash.conf +++ /dev/null @@ -1,34 +0,0 @@ -input { - beats { - port => 5044 - } - - tcp { - port => 50000 - codec => json_lines # JSON 형태의 데이터를 처리 - } -} - -filter { - json { - source => "message" - target => "parsed_message" - } - - mutate { - rename => { "[parsed_message][level]" => "log_level" } - rename => { "[parsed_message][msg]" => "log_message" } - rename => { "[parsed_message][time]" => "@timestamp" } - - remove_field => ["message", "parsed_message"] - } -} - -output { - elasticsearch { - index => "%{[@metadata][service_name]}-%{+YYYY.MM.dd}" - hosts => "elasticsearch:9200" - user => "logstash_internal" - password => "${LOGSTASH_INTERNAL_PASSWORD}" - } -} diff --git a/backend/resources/scripts/ubuntu@dailyroad.site/setup-elk.sh b/backend/resources/scripts/ubuntu@dailyroad.site/setup-elk.sh deleted file mode 100644 index a635086c..00000000 --- a/backend/resources/scripts/ubuntu@dailyroad.site/setup-elk.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -# ELK 스택 설정 초기화 스크립트 - -# 환경 설정 -export ELASTIC_PASSWORD="example" # 변경 필요 -export LOGSTASH_PASSWORD="example" -export KIBANA_PASSWORD="example" -export ELASTIC_VERSION="8.15.3" - -export SERVICE_NAME="dailyroad" - -# 기본 경로 설정 -SETUP_DIR=$(dirname "$(readlink -f "$0")") -DOCKER_ELK_DIR="$SETUP_DIR/../docker-elk" # ELK 스택 클론 경로 - -LOGSTASH_CONFIG="$SETUP_DIR/logstash/logstash.conf" -TEMPLATE_FILE="$SETUP_DIR/elasticsearch/log_index_template.json" -KIBANA_SCRIPTS_DIR="$SETUP_DIR/kibana" - -# 필요 패키지 업데이트 및 설치 -echo "Updating packages..." -sudo apt update -y && sudo apt upgrade -y -echo "Installing Docker and Docker Compose..." -sudo apt install -y docker.io docker-compose - -# Docker와 Docker Compose 설치 확인 -if ! command -v docker &> /dev/null || ! command -v docker-compose &> /dev/null; then - echo "Docker or Docker Compose installation failed. Please check your setup." - exit 1 -fi - -# Docker-ELK 클론 또는 디렉토리로 이동 -if [ ! -d "$DOCKER_ELK_DIR" ]; then - echo "Cloning ELK stack repository to $DOCKER_ELK_DIR..." - git clone https://github.com/deviantony/docker-elk.git "$DOCKER_ELK_DIR" -fi - -cd "$DOCKER_ELK_DIR" || exit - -# .env 파일에서 버전 및 비밀번호 설정 -echo "Setting up environment file..." -sed -i "s/^ELASTIC_VERSION=.*/ELASTIC_VERSION=${ELASTIC_VERSION}/" .env -sed -i "s/^ELASTIC_PASSWORD=.*/ELASTIC_PASSWORD=${ELASTIC_PASSWORD}/" .env -sed -i "s/^LOGSTASH_PASSWORD=.*/LOGSTASH_PASSWORD=${LOGSTASH_PASSWORD}/" .env -sed -i "s/^KIBANA_PASSWORD=.*/KIBANA_PASSWORD=${KIBANA_PASSWORD}/" .env -sed -i "s/^SERVICE_NAME=.*/SERVICE_NAME=${SERVICE_NAME}/" .env -sed -i "s/'//g" .env # 작은 따옴표 제거 - -# Logstash 구성 복사 -if [ -f "$LOGSTASH_CONFIG" ]; then - echo "Copying Logstash configuration..." - cp "$LOGSTASH_CONFIG" logstash/pipeline/logstash.conf -else - echo "Logstash configuration file not found: $LOGSTASH_CONFIG" - exit 1 -fi - -# Elasticsearch 인덱스 템플릿 등록 -if [ -f "$TEMPLATE_FILE" ]; then - echo "Registering Elasticsearch index template..." - curl -u elastic:"${ELASTIC_PASSWORD}" -X PUT "http://localhost:9200/_index_template/${SERVICE_NAME}-template" \ - -H "Content-Type: application/json" \ - -d @"$TEMPLATE_FILE" -else - echo "Index template file not found: $TEMPLATE_FILE" - exit 1 -fi - -# Kibana Painless 스크립트 설정 -if [ -d "$KIBANA_SCRIPTS_DIR" ]; then - for SCRIPT in "$KIBANA_SCRIPTS_DIR"/*.painless; do - SCRIPT_NAME=$(basename "$SCRIPT" .painless) - echo "Adding Kibana Painless script: $SCRIPT_NAME" - curl -u elastic:"${ELASTIC_PASSWORD}" -X POST "http://localhost:9200/_scripts/$SCRIPT_NAME" \ - -H "Content-Type: application/json" \ - -d @"$SCRIPT" - done -else - echo "Kibana scripts directory not found: $KIBANA_SCRIPTS_DIR" -fi - -# 초기 사용자 및 권한 설정 -echo "Setting up initial users and permissions..." -docker-compose up setup - -# ELK 스택 시작 -echo "Starting ELK stack..." -docker-compose up -d - -# Kibana 초기화 대기 -echo "Waiting for Kibana to initialize..." -sleep 60 - -# Logstash 사용자에게 writer 권한 부여 -echo "Assigning writer role to Logstash user..." -curl -u elastic:"${ELASTIC_PASSWORD}" -X PUT "http://localhost:9200/_security/role/logstash_writer" -H "Content-Type: application/json" -d "{ - \"cluster\": [\"manage_index_templates\", \"monitor\", \"manage_ilm\"], - \"indices\": [ - { - \"names\": [\"${SERVICE_NAME}-*\"], - \"privileges\": [\"write\", \"create_index\"] - } - ] -}" - -# ELK 스택 상태 확인 -docker-compose ps - -echo "ELK stack setup completed. Access Kibana at http://localhost:5601 with the default user credentials." diff --git a/backend/src/course/exception/CoursePermissionException.ts b/backend/src/course/exception/CoursePermissionException.ts index e19a1b2b..d848939a 100644 --- a/backend/src/course/exception/CoursePermissionException.ts +++ b/backend/src/course/exception/CoursePermissionException.ts @@ -1,4 +1,4 @@ -import { BaseException } from '../../common/exception/BaseException'; +import { BaseException } from '@src/common/exception/BaseException'; import { HttpStatus } from '@nestjs/common'; export class CoursePermissionException extends BaseException { diff --git a/backend/src/user/exception/UserNotFoundException.ts b/backend/src/user/exception/UserNotFoundException.ts new file mode 100644 index 00000000..d2f9c13f --- /dev/null +++ b/backend/src/user/exception/UserNotFoundException.ts @@ -0,0 +1,11 @@ +import { BaseException } from '@src/common/exception/BaseException'; + +export class UserNotFoundException extends BaseException { + constructor(id: number) { + super({ + code: 2001, + message: `id:${id} 사용자를 찾을 수 없습니다.`, + status: 404, + }); + } +} diff --git a/backend/src/user/user.controller.ts b/backend/src/user/user.controller.ts index 4bbfcb37..ed99a104 100644 --- a/backend/src/user/user.controller.ts +++ b/backend/src/user/user.controller.ts @@ -1,7 +1,15 @@ -import { Controller } from '@nestjs/common'; +import { Controller, Get, UseGuards } from '@nestjs/common'; import { UserService } from './user.service'; +import { JwtAuthGuard } from '@src/auth/JwtAuthGuard'; +import { AuthUser } from '@src/auth/AuthUser.decorator'; @Controller('users') export class UserController { constructor(private readonly userService: UserService) {} + + @Get('/info') + @UseGuards(JwtAuthGuard) + async getUserInfo(@AuthUser() user: AuthUser) { + return await this.userService.getUserInfo(user.userId); + } } diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index 4278da27..61acc2d1 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -1,6 +1,8 @@ import { Injectable } from '@nestjs/common'; import { UserRepository } from './user.repository'; import { CreateUserRequest } from './dto/CreateUserRequest'; +import { UserIconResponse } from '@src/user/dto/UserIconResponse'; +import { UserNotFoundException } from '@src/user/exception/UserNotFoundException'; @Injectable() export class UserService { @@ -22,4 +24,12 @@ export class UserService { const newUser = await this.userRepository.save(user); return { userId: newUser.id, role: newUser.role }; } + + async getUserInfo(userId: number) { + const user = await this.userRepository.findById(userId); + if (!user) { + throw new UserNotFoundException(userId); + } + return UserIconResponse.from(user); + } }