Nome de usuário Unicode com Σ como caractere final causa erro ao carregar página de perfil

Primeiramente, muito obrigado pela sua ajuda! De qualquer forma, é um bug interessante.

O problema é que talvez eu precise alterar o nome de usuário diretamente no banco de dados, pois a rota não está disponível :sweat_smile:

Você poderia me fornecer uma consulta?

Acho que isso não é possível, pois eu acabaria bloqueando muitos nomes que começam com Σ na Grécia (e, essencialmente, quebraria os logins do Facebook para esses usuários). É possível bloquear um padrão regex específico? Assim, eu garantiria que o Σ esteja, pelo menos, no final.

1 curtida

Outro membro se registrou com exatamente o mesmo problema. Meu ponto aqui é que, para nós, isso não é um caso excepcional. Existem literalmente milhares de nomes em grego que usam o Σ (ou ς) no final do nome.

E, infelizmente, dado nosso grupo etário principal (> 40), há muitos membros que têm o nome escrito em maiúsculas no Facebook (:sweat_smile:), então, quando usam o login do Facebook, o nome é copiado para o campo de nome de usuário…

4 curtidas

Eu não me preocuparia com o Postgres. Devemos sempre comparar com username_lower no SQL e não depender do LOWER(), porque username_lower não é apenas a versão em minúsculas do nome de usuário. Também aplicamos a normalização Unicode.

Concordo. Adicionar uma solução alternativa ao User.normalize_username deve ser suficiente por enquanto. Já há algumas discussões sobre o bug no Ruby e parece que não há uma solução fácil. No entanto, temos sorte, pois tudo o que precisamos fazer é verificar o último caractere de um nome de usuário. Isso é muito mais fácil do que fazer isso em uma frase completa.

4 curtidas

Bem… como esse nome de usuário seria tratado?

Maiúsculas: ΧΡΗΣΤΟΣ_ΠΑΝΑΓΙΩΤΑΚΟΠΟΥΛΟΣ
Minúsculas: χρηστος_παναγιωτακοπουλος ou χρηστοσ_παναγιωτακοπουλος

O NodeJs lida com isso corretamente, mas se você verificar apenas o último caractere do nome de usuário, o problema persistirá.


(Quase todos os nomes masculinos em grego — tanto primeiros quanto sobrenomes — terminam com Σ)

3 curtidas

Certo. Ainda assim, deve ser muito mais fácil do que uma implementação completa, já que só precisamos nos preocupar com certos símbolos, como sublinhado, hífen e talvez números? Isso deve ser viável.

2 curtidas

Sei que estou me desviando da discussão específica sobre esse bug, mas ao pensar nesse problema, não consigo ignorar o fato de que isso poderia ser evitado.

Descobri que existem algumas rotas de API no Discourse que referenciam um usuário por userId, enquanto outras o referenciam por username. Isso não deveria ser mais consistente (em favor do userId)?

Talvez implementar algo como o que acontece agora com categorias e tags? Ter tanto o username quanto o userId na URL, por exemplo: https://meta.discourse.org/u/chrispanag/4387

Só uma ideia :sweat_smile:

2 curtidas

Isso exigirá um esforço de limpeza; com certeza já vi algumas chamadas de LOWER().

4 curtidas

Isso tem sido levantado ao longo dos anos: Update quotes and mentions when username is changed - #10 by sam

Em 2016, @eviltrout era contra, não tenho certeza de qual é a posição dele hoje em dia.

De qualquer forma, tenho uma solução alternativa no Discourse neste PR:

Ele resolverá o problema de novo cadastro no Facebook convertendo para minúsculas qualquer nome de usuário que comece com sigma. Isso significa que tudo o que você precisa fazer é corrigir o nome de usuário do Spiros e de qualquer outro usuário com sigma final, convertendo para minúsculas, e o problema deve ser resolvido a longo prazo.

(Aprovação do PR pendente)

4 curtidas

Muito obrigado @sam! Sua ajuda foi imensa.

Existe uma maneira de fazer isso pelo console do Rails? (Como o usuário está quebrado, não há como fazer isso pelo painel de administração…)

1 curtida

Sim, isso deve resolver

./launcher enter app
rails c
u = User.find_by(username: 'ΣΠΥΡΟΣ')
u.username = 'σπυρος'
u.username_lower = 'σπυρος'
u.save!
4 curtidas

Ainda não gosto muito de usar IDs em todos os lugares, mas entendo que há muitos casos em que faz sentido.

Nesses casos, eu preferiria algo como id-usuario, onde “usuario” é qualquer coisa que possamos colocar em uma URL. Isso poderia até ser ignorado pelo roteador. Mas, pelo menos, ao compartilhar o link, você teria uma ideia do que está sendo vinculado.

6 curtidas

Em relação ao PostgreSQL, parece que configurar as collations corretas resolve o problema:

➜  discoursesmall git:(master) psql -d discourse_development
psql (13.1 (Ubuntu 13.1-1.pgdg20.10+1))
Digite "help" para obter ajuda.

discourse_development=# SELECT lower('ΣΠΥΡΟΣ');
 lower  
--------
 σπυροσ
(1 linha)

discourse_development=# SELECT lower('ΣΠΥΡΟΣ' COLLATE "und-x-icu"); 
 lower  
--------
 σπυρος
(1 linha)

Fonte: https://www.postgresql.org/message-id/5d80ac2d-3f1f-4d60-88a8-5602eb9978a3%40manitou-mail.org

7 curtidas

Aparentemente, existem outros caracteres Unicode que têm transformações semelhantes, por exemplo: ‘ß’ → ‘SS’ (alemão)

É interessante investigar como eles são tratados pelo Discourse…

Além disso, você também pode conferir este recurso:

Pessoalmente, sou um grande fã do estilo de roteamento do Stack Overflow para usuários:

https://stackoverflow.com/users/17174/sam-saffron

No ecossistema Discourse, isso seria:

https://meta.discourse.org/u/17174/sam-saffron

Isso permite que você tenha o melhor dos dois mundos. Mas sim, entendo perfeitamente a objeção: “Não gosto de ver o número 17174 em nenhum lugar da URL; nomes de usuário são estáveis”.

Dito isso, temos sobrevivido até agora com nossas rotas existentes; é apenas que, de vez em quando, alguns casos extremos aparecem.

5 curtidas

Acho que seria útil usar o ID em vez do nome de usuário (ou ambos, mas dependendo apenas do ID, como explicado acima) pelo menos na página de perfil do usuário, para que o administrador possa alterar o nome de usuário usando a interface do Discourse sem precisar executar o comando no console do Rails caso algo dê errado com o nome de usuário.

Precisamos nos preocupar apenas com os caracteres onde a implementação da conversão para minúsculas em JavaScript e Ruby difere. Não o contrário.

Não há uma regra única sobre como a letra minúscula alemã “ß” é convertida para maiúscula. Pode ser “SS”, “SZ” ou até mesmo a nova letra maiúscula “ẞ” (sim, há uma diferença sutil). Reverter esse processo só é possível para “ẞ”, e isso funciona corretamente tanto no Ruby quanto no JavaScript.


Acho que devemos fazer o seguinte:

  1. Mesclar a solução alternativa de @sam para corrigir o problema imediato
  2. Remover LOWER(username) das consultas SQL, pois é simplesmente uma coisa ruim de se fazer (por exemplo, falta de normalização Unicode)
  3. Esperar que o Ruby corrija o problema subjacente
  4. A longo prazo: Pensar em adicionar IDs de usuário às rotas. Acredito que a parte mais difícil será descobrir como lidar com aspas e menções.
3 curtidas

Não tenho certeza se está relacionado, mas temos alguns usuários com nomes em Unicode e eles estão espalhados pelo /log

ActionView::Template::Error (Nenhuma rota corresponde a {:action=>"show", :controller=>"users", :username=>"ζηεδψ"}, possíveis restrições sem correspondência: [:username])