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 bcbf44e..0000000 Binary files a/__pycache__/config.cpython-311.pyc and /dev/null differ 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 af95f31..28a9cce 100644 Binary files a/instance/database.db and b/instance/database.db differ diff --git a/run.py b/run.py index ebd533e..261f9e1 100644 --- a/run.py +++ b/run.py @@ -1,4 +1,4 @@ -from app import create_default_user, create_app +from app import create_app from app.database import db app = create_app() @@ -6,8 +6,7 @@ app = create_app() if __name__ == "__main__": with app.app_context(): db.create_all() - create_default_user() -print("Banco de dados criado") + print("Banco de dados criado") app.run(debug=True, port=5000)