From 1d80b47a3dad048107f44a35759d8c2bde602d28 Mon Sep 17 00:00:00 2001 From: Ben Miller Date: Tue, 23 Jun 2026 14:06:36 -0500 Subject: [PATCH] feat: implement user authentication, session management, and core database models for notepads, notes, and collaboration features. --- app.py | 1 + blueprints/auth.py | 1 + config.py | 4 +++- models/banned_ip.py | 5 ++++- models/collaborator.py | 3 +++ models/favorite.py | 5 ++++- models/note.py | 3 +++ models/notepad.py | 3 +++ models/user.py | 3 +++ 9 files changed, 25 insertions(+), 3 deletions(-) diff --git a/app.py b/app.py index 08536d3..3c82eca 100644 --- a/app.py +++ b/app.py @@ -32,3 +32,4 @@ with app.app_context(): if __name__ == "__main__": app.run(debug=True) + diff --git a/blueprints/auth.py b/blueprints/auth.py index 2711281..08f9ddf 100644 --- a/blueprints/auth.py +++ b/blueprints/auth.py @@ -50,6 +50,7 @@ def login(): user.last_ip = ip_address db.session.commit() + session.permanent = True session['user_id'] = user.id return jsonify({'message': 'Login successful', 'user': user.to_dict()}), 200 diff --git a/config.py b/config.py index 72a205d..26cb6e1 100644 --- a/config.py +++ b/config.py @@ -1,4 +1,5 @@ import os +from datetime import timedelta basedir = os.path.abspath(os.path.dirname(__file__)) @@ -6,4 +7,5 @@ class Config: SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-key-very-secret' SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \ 'sqlite:///' + os.path.join(basedir, 'spotnotes.db') - SQLALCHEMY_TRACK_MODIFICATIONS = False \ No newline at end of file + SQLALCHEMY_TRACK_MODIFICATIONS = False + PERMANENT_SESSION_LIFETIME = timedelta(days=30) \ No newline at end of file diff --git a/models/banned_ip.py b/models/banned_ip.py index d72829a..c1b6a84 100644 --- a/models/banned_ip.py +++ b/models/banned_ip.py @@ -4,4 +4,7 @@ from datetime import datetime class BannedIP(db.Model): id = db.Column(db.Integer, primary_key=True) ip_address = db.Column(db.String(45), unique=True, nullable=False) - created_at = db.Column(db.DateTime, default=datetime.utcnow) \ No newline at end of file + created_at = db.Column(db.DateTime, default=datetime.utcnow) + + def __init__(self, **kwargs): + super().__init__(**kwargs) \ No newline at end of file diff --git a/models/collaborator.py b/models/collaborator.py index d13ff0b..8fb4dcf 100644 --- a/models/collaborator.py +++ b/models/collaborator.py @@ -15,6 +15,9 @@ class Collaborator(db.Model): db.UniqueConstraint('notepad_id', 'user_id', name='unique_collaborator'), ) + def __init__(self, **kwargs): + super().__init__(**kwargs) + def to_dict(self): return { 'id': self.id, diff --git a/models/favorite.py b/models/favorite.py index d0afb29..efbf776 100644 --- a/models/favorite.py +++ b/models/favorite.py @@ -7,4 +7,7 @@ class Favorite(db.Model): __table_args__ = ( db.UniqueConstraint('user_id', 'notepad_id', name='unique_favorite'), - ) \ No newline at end of file + ) + + def __init__(self, **kwargs): + super().__init__(**kwargs) \ No newline at end of file diff --git a/models/note.py b/models/note.py index aa9dd44..51b071d 100644 --- a/models/note.py +++ b/models/note.py @@ -11,6 +11,9 @@ class Note(db.Model): is_hidden = db.Column(db.Boolean, default=False) notepad_id = db.Column(db.Integer, db.ForeignKey('notepad.id'), nullable=False) + def __init__(self, **kwargs): + super().__init__(**kwargs) + def to_dict(self): return { 'id': self.id, diff --git a/models/notepad.py b/models/notepad.py index 08dea8f..b7d14b3 100644 --- a/models/notepad.py +++ b/models/notepad.py @@ -12,6 +12,9 @@ class Notepad(db.Model): notes = db.relationship('Note', backref='notepad', lazy='dynamic', cascade="all, delete-orphan") + def __init__(self, **kwargs): + super().__init__(**kwargs) + def to_dict(self): return { 'id': self.id, diff --git a/models/user.py b/models/user.py index db24207..199436c 100644 --- a/models/user.py +++ b/models/user.py @@ -11,6 +11,9 @@ class User(db.Model): is_banned = db.Column(db.Boolean, default=False) last_ip = db.Column(db.String(45)) + def __init__(self, **kwargs): + super().__init__(**kwargs) + def set_password(self, password): self.password_hash = generate_password_hash(password)