From fd7525548ba6435bc6ef368df20fed3f9cf16872 Mon Sep 17 00:00:00 2001 From: Antero Asafe Date: Sat, 17 May 2025 19:22:26 -0400 Subject: [PATCH] =?UTF-8?q?Reorganiza=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- __pycache__/config.cpython-311.pyc | Bin 267 -> 0 bytes app/__init__.py | 30 ++++------ app/auth.py | 31 ---------- app/models/{documentos.py => Documento.py} | 8 ++- app/models/Usuario.py | 21 +++++++ app/models/organizacao.py | 9 ++- app/models/user.py | 15 ----- app/routes/documentos.py | 44 ++++++++++++++ app/routes/documentos_routes.py | 63 --------------------- app/routes/organizacao.py | 40 +++++++++++++ app/routes/organizacao_routes.py | 46 --------------- app/routes/user_routes.py | 55 ------------------ app/routes/usuario.py | 44 ++++++++++++++ instance/database.db | Bin 16384 -> 49152 bytes run.py | 5 +- 16 files changed, 175 insertions(+), 239 deletions(-) delete mode 100644 __pycache__/config.cpython-311.pyc delete mode 100644 app/auth.py rename app/models/{documentos.py => Documento.py} (66%) create mode 100644 app/models/Usuario.py delete mode 100644 app/models/user.py create mode 100644 app/routes/documentos.py delete mode 100644 app/routes/documentos_routes.py create mode 100644 app/routes/organizacao.py delete mode 100644 app/routes/organizacao_routes.py delete mode 100644 app/routes/user_routes.py create mode 100644 app/routes/usuario.py diff --git a/.vscode/settings.json b/.vscode/settings.json index 1583620..5ed57c8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "python.analysis.extraPaths": [ "./app" - ] + ], + "python.analysis.autoImportCompletions": true } \ No newline at end of file diff --git a/__pycache__/config.cpython-311.pyc b/__pycache__/config.cpython-311.pyc deleted file mode 100644 index bcbf44ee5d9202621acef0b8597bcec9a8f9abdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 267 zcmZ3^%ge<81PN=Oq^AJs#~=<2FhLog#ej_I3@HpLj5!QZ3@J=ej48}fOeu`P44N!2 zL5lpUM2ib^GD}je^!4>q5=#=35{pyyQj**>nQt-W7vB;O4)k&KarSWajf{733~_XF z40eqV4f4Dtha?daE`L|7~<*g7rc_;GsyT~YWf-ZxvBbzc_pbu`H97e zX{iS0`njojCHX~}iTcU;d1;yHdIgogIBatBQ%ZAE?TR>o+8BYjSOG|UU}j`wyurZP Y0EQ2w3@OV diff --git a/app/__init__.py b/app/__init__.py index 000935b..41696f8 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,36 +1,28 @@ from flask import Flask from app.database import db -from app.models.user import User -from app.routes.user_routes import user_bp from werkzeug.security import generate_password_hash -def create_default_user(): - # Verifica se o banco de dados está vazio - user = User.query.first() +# Importação dos modelos para garantir o mapeamento completo +from app.models import Usuario, Organizacao - if not user: - # Cria um usuário padrão com senha "senha123" - default_user = User( - name="admin", - email="admin@example.com", - password=generate_password_hash("senha123", method="pbkdf2:sha256") - ) +# Importação dos blueprints +from app.routes.usuario import usuarios_bp +from app.routes.organizacao import organizacoes_bp +from app.routes.documentos import documentos_bp - # Adiciona o usuário no banco de dados - db.session.add(default_user) - db.session.commit() - print("Usuário padrão criado com sucesso!") def create_app(): app = Flask(__name__) app.config.from_object("config") + # Inicializa a extensão SQLAlchemy db.init_app(app) - - # Registrar Blueprints - app.register_blueprint(user_bp, url_prefix="/users") + # Registra os blueprints + app.register_blueprint(usuarios_bp) + app.register_blueprint(organizacoes_bp) + app.register_blueprint(documentos_bp) return app diff --git a/app/auth.py b/app/auth.py deleted file mode 100644 index f1d80aa..0000000 --- a/app/auth.py +++ /dev/null @@ -1,31 +0,0 @@ -from functools import wraps -from flask import request, jsonify -import jwt - -from app.models.user import User # ou Organization - -SECRET_KEY = "sua_chave_secreta" - -def generate_token(user): - token = jwt.encode({"id": user.id}, SECRET_KEY, algorithm="HS256") - return token - -def token_required(f): - @wraps(f) - def decorated(*args, **kwargs): - token = None - - if 'Authorization' in request.headers: - token = request.headers['Authorization'].split(" ")[1] # Bearer - - if not token: - return jsonify({"message": "Token ausente!"}), 401 - - try: - data = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) - current_user = User.query.get(data["id"]) - except: - return jsonify({"message": "Token inválido!"}), 401 - - return f(current_user, *args, **kwargs) - return decorated diff --git a/app/models/documentos.py b/app/models/Documento.py similarity index 66% rename from app/models/documentos.py rename to app/models/Documento.py index 94fce8b..7745b1c 100644 --- a/app/models/documentos.py +++ b/app/models/Documento.py @@ -1,13 +1,15 @@ +# documento.py from app.database import db import uuid -class Documento(db.Model): + +class Documento(db.Model): # __tablename__ = 'documentos' id = db.Column(db.UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) nome_arquivo = db.Column(db.String, nullable=False) caminho_arquivo = db.Column(db.String, nullable=False) - usuario_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) + usuario_id = db.Column(db.Integer, db.ForeignKey('usuario.id'), nullable=False) criado_em = db.Column(db.DateTime(timezone=True), server_default=db.func.now(), nullable=False) - usuario = db.relationship('User', back_populates='documentos') \ No newline at end of file + usuario = db.relationship('Usuario', back_populates='documentos') diff --git a/app/models/Usuario.py b/app/models/Usuario.py new file mode 100644 index 0000000..8d5bc54 --- /dev/null +++ b/app/models/Usuario.py @@ -0,0 +1,21 @@ +# usuario.py +from app.database import db + + +class Usuario(db.Model): + __tablename__ = 'usuario' + + id = db.Column(db.Integer, primary_key=True, + autoincrement=True, unique=True) + nome = db.Column(db.String, nullable=False) + email = db.Column(db.String, nullable=False, unique=True) + senha_hash = db.Column(db.String, nullable=False) + organizacao_id = db.Column(db.Integer, db.ForeignKey( + 'organizacao.id'), nullable=False) + criado_em = db.Column(db.DateTime(timezone=True), + server_default=db.func.now(), nullable=False) + atualizado_em = db.Column(db.DateTime( + timezone=True), onupdate=db.func.now()) + + organizacao = db.relationship('Organizacao', back_populates='usuarios') + documentos = db.relationship('Documento', back_populates='usuario') diff --git a/app/models/organizacao.py b/app/models/organizacao.py index c5cf266..381fa09 100644 --- a/app/models/organizacao.py +++ b/app/models/organizacao.py @@ -1,10 +1,13 @@ from app.database import db + class Organizacao(db.Model): __tablename__ = 'organizacao' - id = db.Column(db.Integer, primary_key=True, autoincrement=True, unique=True) + id = db.Column(db.Integer, primary_key=True, + autoincrement=True, unique=True) nome = db.Column(db.String, nullable=False, unique=True) - criado_em = db.Column(db.DateTime(timezone=True), server_default=db.func.now(), nullable=False) + criado_em = db.Column(db.DateTime(timezone=True), + server_default=db.func.now(), nullable=False) - usuarios = db.relationship('User', back_populates='organizacao') \ No newline at end of file + usuarios = db.relationship('Usuario', back_populates='organizacao') diff --git a/app/models/user.py b/app/models/user.py deleted file mode 100644 index 255f37b..0000000 --- a/app/models/user.py +++ /dev/null @@ -1,15 +0,0 @@ -from app.database import db - -class User(db.Model): - __tablename__ = 'users' - - id = db.Column(db.Integer, primary_key=True, autoincrement=True, unique=True) - nome = db.Column(db.String, nullable=False) - email = db.Column(db.String, nullable=False, unique=True) - senha_hash = db.Column(db.String, nullable=False) - organizacao_id = db.Column(db.Integer, db.ForeignKey('organizacao.id'), nullable=False) - criado_em = db.Column(db.DateTime(timezone=True), server_default=db.func.now(), nullable=False) - atualizado_em = db.Column(db.DateTime(timezone=True), onupdate=db.func.now()) - - organizacao = db.relationship('Organizacao', back_populates='usuarios') - documentos = db.relationship('Documento', back_populates='usuario') \ No newline at end of file diff --git a/app/routes/documentos.py b/app/routes/documentos.py new file mode 100644 index 0000000..77fd7f9 --- /dev/null +++ b/app/routes/documentos.py @@ -0,0 +1,44 @@ +from flask import Blueprint, request, jsonify +from app.database import db +from app.models import Documento + + +documentos_bp = Blueprint('documentos', __name__, url_prefix='/documentos') + +@documentos_bp.route('/', methods=['GET']) +def get_documentos(): + documentos = Documento.query.all() + documentos_data = [ + { + 'id': str(doc.id), + 'nome_arquivo': doc.nome_arquivo, + 'caminho_arquivo': doc.caminho_arquivo, + 'usuario_id': doc.usuario_id, + 'criado_em': doc.criado_em + } + for doc in documentos + ] + return jsonify(documentos_data), 200 + +@documentos_bp.route('/', methods=['POST']) +def create_documento(): + data = request.get_json() + if not all(k in data for k in ('nome_arquivo', 'caminho_arquivo', 'usuario_id')): + return jsonify({'error': 'Campos obrigatórios ausentes'}), 400 + + try: + novo_documento = Documento( + nome_arquivo=data['nome_arquivo'], + caminho_arquivo=data['caminho_arquivo'], + usuario_id=data['usuario_id'] + ) + db.session.add(novo_documento) + db.session.commit() + + return jsonify({ + 'message': 'Documento criado com sucesso', + 'id': str(novo_documento.id) + }), 201 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 diff --git a/app/routes/documentos_routes.py b/app/routes/documentos_routes.py deleted file mode 100644 index 5e2ee0d..0000000 --- a/app/routes/documentos_routes.py +++ /dev/null @@ -1,63 +0,0 @@ -from flask import Blueprint, jsonify, request -from app.auth import token_required -from app.models.documentos import document -from app.database import db - -document_bp = Blueprint("documents", __name__) - -# Listar todos os documentos -@document_bp.route("/", methods=["GET"]) -@token_required -def get_documents(self): - documents = document.query.all() - return jsonify([ - {"id": d.id, "title": d.title, "content": d.content, "owner_id": d.user_id} - for d in documents - ]) - -# Criar um novo documento -@document_bp.route("/", methods=["POST"]) -@token_required -def create_document(self): - data = request.get_json() - title = data.get("title") - content = data.get("content") - - new_doc = document(title=title, content=content, user_id=self.id) # self.id vem do token - - db.session.add(new_doc) - db.session.commit() - - return jsonify({"message": "Documento criado com sucesso!", "document_id": new_doc.id}), 201 - -# Obter um documento específico -@document_bp.route("/", methods=["GET"]) -@token_required -def get_document(self, document_id): - document = document.query.get_or_404(document_id) - return jsonify({ - "id": document.id, - "title": document.title, - "content": document.content, - "owner_id": document.user_id - }) - -# Atualizar um documento -@document_bp.route("/", methods=["PUT"]) -@token_required -def update_document(self, document_id): - document = document.query.get_or_404(document_id) - data = request.get_json() - - document.title = data.get("title", document.title) - document.content = data.get("content", document.content) - - db.session.commit() - return jsonify({"message": "Documento atualizado com sucesso!"}) - -# Deletar um documento -@document_bp.route("/", methods=["DELETE"]) -@token_required -def delete_document(self, document_id): - document = document.query.get_or_404(document_id) - db.session.delete(document) diff --git a/app/routes/organizacao.py b/app/routes/organizacao.py new file mode 100644 index 0000000..2d1ed64 --- /dev/null +++ b/app/routes/organizacao.py @@ -0,0 +1,40 @@ +from flask import Blueprint, request, jsonify +from app.database import db +from app.models import Organizacao # ajuste conforme sua estrutura + +organizacoes_bp = Blueprint('organizacoes', __name__, url_prefix='/organizacoes') + +@organizacoes_bp.route('/', methods=['GET']) +def get_organizacoes(): + organizacoes = Organizacao.query.all() + data = [ + { + 'id': org.id, + 'nome': org.nome, + 'criado_em': org.criado_em + } + for org in organizacoes + ] + return jsonify(data), 200 + +@organizacoes_bp.route('/', methods=['POST']) +def create_organizacao(): + data = request.get_json() + if not data or 'nome' not in data: + return jsonify({'error': 'O campo "nome" é obrigatório'}), 400 + + if Organizacao.query.filter_by(nome=data['nome']).first(): + return jsonify({'error': 'Já existe uma organização com este nome'}), 409 + + try: + nova_org = Organizacao(nome=data['nome']) + db.session.add(nova_org) + db.session.commit() + + return jsonify({ + 'message': 'Organização criada com sucesso', + 'id': nova_org.id + }), 201 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 diff --git a/app/routes/organizacao_routes.py b/app/routes/organizacao_routes.py deleted file mode 100644 index df191e6..0000000 --- a/app/routes/organizacao_routes.py +++ /dev/null @@ -1,46 +0,0 @@ -from flask import Blueprint, jsonify, request -from app.auth import generate_token, token_required -from app.models.organizacao import organization -from app.database import db -from werkzeug.security import generate_password_hash, check_password_hash - -organization_bp = Blueprint("organizations", __name__) - -@organization_bp.route("/", methods=["GET"]) -@token_required -def get_organizations(self): - organizations = organization.query.all() - return jsonify([{"id": o.id, "name": o.name, "email": o.email} for o in organizations]) - -@organization_bp.route("/", methods=["POST"]) -def create_organization(self): - data = request.get_json() - name = data.get("name") - email = data.get("email") - password = data.get("password") - - if organization.query.filter_by(email=email).first(): - return jsonify({"message": "Organização já existe!"}), 400 - - hashed_password = generate_password_hash(password, method="pbkdf2:sha256") - - new_org = organization(name=name, email=email, password=hashed_password) - db.session.add(new_org) - db.session.commit() - - return jsonify({"message": "Organização registrada com sucesso!"}), 201 - -@organization_bp.route("/login", methods=["POST"]) -def login_organization(): - data = request.get_json() - email = data.get("email") - password = data.get("password") - - organization = organization.query.filter_by(email=email).first() - - if not organization or not check_password_hash(organization.password, password): - return jsonify({"message": "Credenciais inválidas!"}), 401 - - token = generate_token(organization) - - return jsonify({"message": "Login bem-sucedido", "token": token}), 200 diff --git a/app/routes/user_routes.py b/app/routes/user_routes.py deleted file mode 100644 index 79b8091..0000000 --- a/app/routes/user_routes.py +++ /dev/null @@ -1,55 +0,0 @@ -from flask import Blueprint, jsonify, request -from app.auth import generate_token, token_required -from app.models.user import User -from app.database import db -from werkzeug.security import generate_password_hash, check_password_hash - -user_bp = Blueprint("users", __name__) - -@user_bp.route("/", methods=["GET"]) -@token_required # Protege a rota -def get_users(self): - users = User.query.all() # select * from User - return jsonify([{"id": u.id, "name": u.name, "email": u.email} for u in users]) - -@user_bp.route("/", methods=["POST"]) -def create_user(self): - data = request.get_json() - print(data) - nome = data.get("nome") - email = data.get("email") - senha = data.get("senha") - - # Verificar se o usuário já existe - if User.query.filter_by(email=email).first(): - return jsonify({"message": "Usuário já existe!"}), 400 - - # Gerar senha criptografada - hashed_password = generate_password_hash(senha, method="pbkdf2:sha256") - - # Criar novo usuário - new_user = User(nome=nome, email=email, senha=senha) - - # Adicionar e salvar no banco de dados - db.session.add(new_user) - db.session.commit() - - return jsonify({"message": "Usuário registrado com sucesso!"}), 201 - -# Rota para login de usuário -@user_bp.route("/login", methods=["POST"]) -def login_user(): - data = request.get_json() - print(data) - - email = data.get("email") - senha = data.get("senha") - - user = User.query.filter_by(email=email).first() - - if not user or not check_password_hash(user.senha, senha): - return jsonify({"message": "Credenciais inválidas!"}), 401 - - token = generate_token(user) - - return jsonify({"message": "Login bem-sucedido", "token": token}), 200 diff --git a/app/routes/usuario.py b/app/routes/usuario.py new file mode 100644 index 0000000..51c1e45 --- /dev/null +++ b/app/routes/usuario.py @@ -0,0 +1,44 @@ +from flask import Blueprint, request, jsonify +from app.database import db +from app.models import Usuario # nome correto do modelo + +usuarios_bp = Blueprint('usuarios', __name__, url_prefix='/usuarios') + + +@usuarios_bp.route('/', methods=['GET']) +def get_usuarios(): + usuarios = Usuario.query.all() + usuarios_data = [ + { + 'id': usuario.id, + 'nome': usuario.nome, + 'email': usuario.email, + 'organizacao_id': usuario.organizacao_id, + 'criado_em': usuario.criado_em, + 'atualizado_em': usuario.atualizado_em + } + for usuario in usuarios + ] + return jsonify(usuarios_data), 200 + + +@usuarios_bp.route('/', methods=['POST']) +def create_usuario(): + data = request.get_json() + if not all(k in data for k in ('nome', 'email', 'senha_hash', 'organizacao_id')): + return jsonify({'error': 'Campos obrigatórios ausentes'}), 400 + + if Usuario.query.filter_by(email=data['email']).first(): + return jsonify({'error': 'E-mail já está em uso'}), 409 + + novo_usuario = Usuario( + nome=data['nome'], + email=data['email'], + senha_hash=data['senha_hash'], + organizacao_id=data['organizacao_id'] + ) + + db.session.add(novo_usuario) + db.session.commit() + + return jsonify({'message': 'Usuário criado com sucesso', 'id': novo_usuario.id}), 201 diff --git a/instance/database.db b/instance/database.db index af95f31b3a136ed41edf907fb333089c80209e11..28a9ccee07607c8ec8e59353d694c3a67c54564b 100644 GIT binary patch literal 49152 zcmeI&Z*SW~9KdnANs}gNXAr9_RB5`>2dfdC)=twNOrV+8ErB%M(gZY~ShvKbMs-fh zpJ{_fEq~q!&v^?&ViFH|!h7HuJVoLOw&yJNmQ0;AG%5O8ihTB+?YqzK&dJ3-yi@ZB zo;XsyKn}z;?JZ5$wOc}Hnzj&r7Q@eInGX~B(MGt|Q|W2R1?|d@){^m$Rw+HvjQ5S- zFZfHBE^ICRTlsMD@5NtAPb$$>SP(z}0R#|0009JEN#M*b7tPgG{rmlaym#VtRC^eB z-GScbqv_GynV!U6hmrH&}v|802Q9o#kdaG9ZK$J^e6?m@f-5>f7l=$3k zY=2@mG6mW)@Vm$ArDcZwq3rp}4KGlwH=RA_xl{Cf*-@?+h@G%%&Fa1*cAQa>QRyPaWyQ_ zaCV*W%-hbPNOs4El&x!(g1NV7)9b7(HR9RZdn|@biA_F&crO0mBekMR50z8X>m)`-K`{1-dH$K@y(=o>GaEd z(Og^8&%TWVoVt7}IiCr1DkB+OuN3U||2QZ{>`_m%%GUKl!K|)Lqf52J-AZi~ug{0?}u$N2i@)vH#f@|l7DV)mr^ zk3#x%B$chpa|QF}^0b)7Eet!i*UN=pF!9WLDNN*ypEcu8d~!u+JB|3f=hFG&Aegv<&h`51FxrKlpN=qdYEs0 zs($@ReXXP#XOzP><&4Lg@rUu)`0I@~kP0Ax00IagfB*srAbB=KnJsT$+Xe z0tg_000IagfB*srAb>z35WWA;^MASn0tg_000IagfB*srAbkvQy z0R#|0009ILKmY**5QqeL|DS$<00IagfB*srAbjO)V@wMXKmY**5I_I{1Q0*~ f0R#}>`9FOC0R#|0009ILKmY**5I_Kd*%$Z^8s#3z delta 59 zcmZo@U~Xt&oFFa8%D}+D0>m)DG*QP`n3X{