feat: adiciona username e banner ao usuario - #12
Conversation
|
|
Atualização: validei tudo contra um Postgres real (subi um container Postgres 16 descartável só pra isso, credenciais via Rodei Aproveitei e confirmei a convenção real de nome de banco contra os secrets do Infisical: só Conferi os dados inseridos: |
…lign schema with production (#13) pr #12 was squash-merged keeping only its first commit (schema.sql username/banner) -- the six commits after it (dataload split into auth/core connections, column-name fixes, csv-driven text/images, connection.py and makefile fixes, databases.py removal) never made it into main. This restores all of that from the feat/user-profile-fields branch, plus new fixes found by actually running dataload against the real qa databases: - company.fk_address/fk_business_contact, local_unit.fk_address, technician_affiliation.fk_company, technical_project.fk_requester/ fk_local_unit/status/start_date are NOT NULL in the real schema -- dataload was treating them as optional. - certification has a completely different real structure (fk_technician, type and information required; name/issuer/ description/validity optional) -- rewritten to match, and moved after seed_technician in the seed order since it now depends on it. - technical_company is a real table this schema never had (added, no seed yet -- not part of the current ask). - federated_identity and inventory have composite UNIQUE constraints that random picks with replacement could violate at higher row counts -- both now sample without replacement/dedupe. - db/core/seed.sql's second company insert was missing fk_address/ fk_business_contact for the same reason. Verified end to end against the real coredbqa/authdbqa (qa environment, credentials via infra-platform/scripts/extract-env.ps1): both databases seed cleanly with no errors.




Objetivo
Dar a todo usuário a capacidade de ter avatar, banner de perfil e um
username/handle (
@user) público, distinto do nome legal emperson.name.De quebra: auditei
db/core/db/authinteiros contra as entidades reais deapi-core/api-auth, corrigi o que estava fora de sincronia, e coloquei omake dataloadpara efetivamente funcionar — populandocoredbeauthdbjuntos, com dados em português e corretos (CPF/CNPJ com dígito verificador
válido, texto livre vindo de bancos de frases curados em vez de lorem
pseudo-latino do Faker). Isso desbloqueia consumir os dados no
databricks-sync/databricks-analytics.PR irmã em
api-core: Solierrr/api-core#52(adiciona
username/bannerna entidadeUser, já quedb/core/schema.sqlse declara reconstruído a partir das entidades reais — sem isso as colunas
novas ficariam sem correspondência real).
Alterações
Schema (
users) + auditoria completadb/core/db/authdb/core/schema.sql+migrations/V1__create_core_schema.sql: adicionausers.username(VARCHAR(30),UNIQUE,CHECK ~ '^[a-z0-9_]{3,30}$')e
users.banner(VARCHAR(255), mesmo padrão doavatarjá existente).db/core/db/authinteiros contraas entidades JPA reais de
api-core/api-auth.db/authbateu 100% (umacópia fiel da migration Flyway real).
db/coretinha 4 colunas declaradascomo
TEXTque na entidade real (semcolumnDefinition) sãoVARCHAR(255)por padrão do Hibernate:position.accesses,professional_review.comment,proposal.notes,unit_specifications.specifications/location_photos— corrigido parabater com o banco real.
scripts/dataload.py— reescrita para funcionar de ponta a pontamisturados) numa única conexão psycopg2 — mas
auth_usere afins vivemem
authdb,userse o resto emcoredb, dois bancos Postgresfisicamente separados.
Seederagora recebe a conexão por fase(
use_connection);main()rodaAUTH_STEPScontraauthdb, comita, esó depois roda
CORE_STEPScontracoredb(que referencia osauth_user.idjá gerados).self.insert(...)referenciavamtabelas que nunca existiram (
media_asset,company_photo,model_photo,local_unit_photo,offer_service_region,offer_translation,session_authentication_method— MFA na verdade é umTEXT[]direto emauth_session.authentication_methods) ou colunas erradas (fk_useremvez de
user_id/fk_users,fk_session→session_id,fk_replaced_by→replaced_by_id,fk_accepted_by→accepted_by,id_position/id_permissiontrocados,model.width/lengthem vez dedimension,company.business_type/slug,offer.slug/discount_percentage/etc.,technician.slug,energy_bill.photo_url/photo_public_id— nenhuma dessas colunas existeno schema real). Removido/corrigido tudo; validei com um dry-run completo
(mock de conexão) rodando as 50 tabelas sem exceção, e um script que
compara cada
self.insert()contra as colunas reais dedb/core+db/auth— 0 mismatches.recompute_proposal_totalschamavafn_proposal_total(), uma functionque nunca existiu (
db/core/proceduresestá vazio) — trocado por umaagregação SQL direta (
proposal_itemxoffer).cpf/cnpjagora usamFaker.cpf()/Faker.cnpj()(dígito verificador válido) em vez de dígitosaleatórios.
FAKE.bs()(inglês) eFAKE.text()/FAKE.sentence()(lorempseudo-latino, mesmo com locale
pt_BR) foram trocados por bancos defrases em português curados (
scripts/data/catalog/certification_name.csv,certification_description.csv,technical_service_purpose.csv,review_comment.csv,business_note.csv,security_event_note.csv) vianovo helper
pick_text().CSVs de imagem — banner único e fallback seguro
media_pool()não levanta mais erro em CSV vazio;pick_media()cai numplaceholder do Faker enquanto o CSV não for preenchido.
hero.csv/company_banner.csvviraram um únicobanner.csv, populadocom 50 imagens do Unsplash (paisagem urbana, natureza, espaço, animais,
oceano — 10 de cada) já enviadas para o Cloudinary (
cloud solaria,pasta
console), consumido tanto porusers.bannerquanto (quandocompanyganhar banner) por empresa.unit_specifications.location_photos(campo real, antes sóFAKE.url()genérico) agora usaunit_specifications_photos.csv.Makefile +
scripts/connection.pyscripts/connection.pyusava um esquema de env vars (CORE_HOST,AUTH_NAME, etc.) que não existe em.env.example—make dataloadquebrava na conexão. Agora reusa exatamente as mesmas variáveis
HOST/PORT/USER/PASSWORD/ENVIRONMENTque o Makefile já usa,construindo o nome do banco do mesmo jeito (
$(TARGET)$(SUFIX)).scripts/databases.py(o mapeamento antigo, que também estava errado)foi removido.
make dataloadnão recebe maisTARGET: como uma execução semprepopula os dois bancos juntos (dependência
users.auth_id→auth_user.id), não fazia sentido escolher um banco só.Fora de escopo (mantido de propósito)
offer_translation/company_photo/model_photo/etc. eram tabelasfictícias — removi as chamadas em vez de desenhar esse schema do zero,
já que ninguém pediu multi-idioma de oferta ou fotos de empresa/modelo
ainda. Se quiser essa funcionalidade, é um schema novo (fora do pedido
original de usuário).
Makefilefora dedataload(
migrateaponta pramigrations/na raiz em vez dedb/$(TARGET)/migrations/;resetcria um banco$(TARGET)que não é o mesmo que$(TARGET)$(SUFIX)usado no resto) — sinalizados numa conversa anterior, não pedidos agora.
Tipo de mudança
Banco(s) afetado(s)
coredbeauthdb(odataloadagora sempre popula os dois juntos)É destrutiva ou difícil de reverter?
Não é destrutiva (só adiciona colunas/corrige tipos e arquivos de dados).
users.usernameéNOT NULL; num banco com dados reais pré-existentes oALTER TABLEequivalente precisaria de backfill — não se aplica a um bancocriado do zero via
schema.sql.Como validar
Não tive acesso a um Postgres válido neste ambiente para rodar de ponta a
ponta contra um banco real (tentei, autenticação falhou). Validei tudo que
dava para validar sem banco: sintaxe Python, dry-run completo das 50 tabelas
com conexão mockada (0 exceções), comparação automatizada de cada
self.insert()contra as colunas reais dedb/core+db/auth(0mismatches), 2000 usernames gerados contra o regex do
CHECK, geração deCPF/CNPJ com dígito verificador válido. Recomendo fortemente rodar o passo
acima contra um banco real antes do merge.