From f6dc93a9ab010845b0192f0eac9c1688ed2a02ca Mon Sep 17 00:00:00 2001 From: hina ntki Date: Mon, 12 Aug 2024 17:11:32 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=BB=E3=83=83=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E5=88=A4=E5=AE=9A=E5=9B=9E=E3=82=8A=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +++- _.env | 1 + docker-compose.yml | 2 +- web/auth.py | 42 ++++++++++++++++++++++++++++++++++++------ web/models.py | 7 ++++++- 5 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 _.env diff --git a/.gitignore b/.gitignore index 90f8fbb..a7dd54b 100644 --- a/.gitignore +++ b/.gitignore @@ -173,4 +173,6 @@ poetry.toml # LSP config files pyrightconfig.json -# End of https://www.toptal.com/developers/gitignore/api/python \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/python + +web/data/ \ No newline at end of file diff --git a/_.env b/_.env new file mode 100644 index 0000000..8141df0 --- /dev/null +++ b/_.env @@ -0,0 +1 @@ +DISCORD_TOKEN= \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 24bfeed..7492ea4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: - ./bot:/bot - ./bucket:/bot/bucket environment: - - DISCORD_TOKEN=MTIyNjIwMTA4ODg1NjgyMTg4MQ.GH0q-p.5A8k4UCGXK5UT6g4uCksFNHhAky9EvRQLuZckQ + - DISCORD_TOKEN=${DISCORD_TOKEN} web: build: ./web volumes: diff --git a/web/auth.py b/web/auth.py index c66ceda..7232bab 100644 --- a/web/auth.py +++ b/web/auth.py @@ -1,12 +1,16 @@ -from flask import request, session, redirect, url_for, render_template, g, jsonify +from flask import request, session, redirect, url_for, render_template, jsonify import bcrypt import secrets from db import get_db from models import Account, ActiveSession import logging +from datetime import datetime, timedelta logger = logging.getLogger(__name__) +# セッションタイムアウトの設定(3分) +SESSION_TIMEOUT = timedelta(minutes=5) + def login_required(f): def decorated_function(*args, **kwargs): if not check_login(session, logger): @@ -19,12 +23,24 @@ def check_login(session, logger): if 'logged_in' not in session or not session['logged_in']: logger.info("セッションにログイン情報がありません") return False + + # セッションタイムアウトのチェック + last_access_time = session.get('last_access_time') + if last_access_time: + last_access_time = datetime.strptime(last_access_time, '%Y-%m-%d %H:%M:%S.%f') + if datetime.now() - last_access_time > SESSION_TIMEOUT: + logger.info("セッションがタイムアウトしました") + logout() # セッションをクリアし、ログアウト + return False db = get_db() active_session_count = db.query(ActiveSession).filter_by(session_id=session['session_id']).count() if active_session_count != 1: logger.info(f"セッションID {session['session_id']} のアクティブセッション数: {active_session_count}") return False + + # 最後のアクセス時間を更新 + session['last_access_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') return True def login(): @@ -33,12 +49,26 @@ def login(): password = request.form['password'].encode('utf-8') db = get_db() account = db.query(Account).filter_by(user_id=user_id).first() + if account and bcrypt.checkpw(password, account.password.encode('utf-8')): - active_sessions = db.query(ActiveSession).count() - if active_sessions >= 1: - return "他のユーザーが既にログインしています。", 403 + # 既存のアクティブセッションをチェック + existing_session = db.query(ActiveSession).filter_by(user_id=account.id).first() + + if existing_session: + # セッションのタイムアウトを確認 + last_active = existing_session.last_active + if last_active and datetime.now() - last_active > SESSION_TIMEOUT: + # セッションがタイムアウトしている場合、削除 + db.delete(existing_session) + db.commit() + else: + return "他のユーザーが既にログインしています。", 403 + + # 新しいセッションの作成 session['logged_in'] = True - new_session = ActiveSession(session_id=session['session_id']) + session['session_id'] = secrets.token_hex(16) + session['last_access_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') + new_session = ActiveSession(session_id=session['session_id'], user_id=account.id, last_active=datetime.now()) db.add(new_session) db.commit() return redirect(url_for('index_route')) @@ -48,7 +78,7 @@ def login(): def logout(): db = get_db() - db.query(ActiveSession).filter_by(session_id=session['session_id']).delete() + db.query(ActiveSession).filter_by(session_id=session.get('session_id')).delete() db.commit() session.clear() return redirect(url_for('login_route')) diff --git a/web/models.py b/web/models.py index 196da50..64af5bd 100644 --- a/web/models.py +++ b/web/models.py @@ -1,5 +1,6 @@ -from sqlalchemy import Column, Integer, String, TIMESTAMP +from sqlalchemy import Column, Integer, String, TIMESTAMP, ForeignKey from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship Base = declarative_base() @@ -9,11 +10,15 @@ class Account(Base): user_id = Column(String) password = Column(String) + active_sessions = relationship("ActiveSession", back_populates="account") + class ActiveSession(Base): __tablename__ = 'active_sessions' id = Column(Integer, primary_key=True) session_id = Column(String) last_active = Column(TIMESTAMP) + user_id = Column(Integer, ForeignKey('accounts.id')) + account = relationship("Account", back_populates="active_sessions") class ChannelId(Base): __tablename__ = 'channel_ids'