beyond-all-reason / teiserver

Middleware server for online gaming
https://www.beyondallreason.info/
MIT License
47 stars 47 forks source link

Cannot save community roles in dev environment #272

Closed jauggy closed 2 months ago

jauggy commented 3 months ago

Steps

  1. Run teiserver locally
  2. Launch website and login as root@localhost password
  3. Find a user and edit them
  4. Tick the community roles
  5. Save changes
  6. Go to edit user again. The checkboxes should be ticked but aren't. 1
jauggy commented 3 months ago

@L-e-x-o-n Can you please verify if you get this bug on your local machine or if it's just me?

L-e-x-o-n commented 3 months ago

It doesn't work, no idea why.

AdamChlupacek commented 3 months ago

I can fix this, please assign to me.

StanczakDominik commented 3 months ago

I saw something like this while following https://github.com/beyond-all-reason/teiserver/pull/256, but the difference is that I wasn't able to give my spads bot the Bot role, it wouldn't save it - like you're seeing here. I ended up completely messing up my root permissions and doing mix teiserver.fakedata to sidestep it.

jauggy commented 3 months ago

I saw something like this while following #256, but the difference is that I wasn't able to give my spads bot the Bot role, it wouldn't save it - like you're seeing here. I ended up completely messing up my root permissions and doing mix teiserver.fakedata to sidestep it.

Just tested and I can set someone to bot if I login as root@localhost . Make sure you test with Administrator login because they are the only one who can give bot role.

jere0500 commented 2 months ago

Tldr: I still have the problem, because booleans from the checkboxes are not transferred into the role field.

Unfortunately this issue still persisted for me, maybe it is due to the elixir version (I used 1.14.5) or some dependency behaving differently. (I logged in as root@localhost so that shouldn't be an issue) Thats why I decided to dig into it more.

In a nutshell: 3 files are relevant here:

  1. The html form page for editing the user (where the checkboxes get loaded): https://github.com/beyond-all-reason/teiserver/blob/master/lib/teiserver_web/templates/admin/user/form.html.heex
  2. The change request processing from the form: https://github.com/beyond-all-reason/teiserver/blob/3e13abb6cb79f17c684db2aa8b38fb581724c7e2/lib/teiserver/account/schemas/user.ex#L52
  3. The part where the update gets written into the database: https://github.com/beyond-all-reason/teiserver/blob/3e13abb6cb79f17c684db2aa8b38fb581724c7e2/lib/teiserver/account/libs/user_lib.ex#L169

The Problem

I add IO.inspect() calls to the functions and found out that the attrs that are passed to (2.) from the form (1.) are in another format:

%{
  "Contributor" => "false",
  "Mapping" => "false",
  "permissions" => [],
  "data" => %{
    "bot" => false,
    "chobby_hash" => nil,
    "country" => "??",
    "discord_dm_channel" => nil,
    "discord_dm_channel_id" => nil,
    "discord_id" => nil,
    "email_change_code" => nil,
    "hw_hash" => nil,
    "last_login" => 28609015,
    "last_login_mins" => 28609015,
    "last_login_timex" => "2024-05-24T08:55:12.000625Z",
    "lobby_client" => "SPADS v",
    "lobby_hash" => "57015357 5636bd6e65323f54",
    "moderator" => false,
    "password_hash" => "$argon2id$v=19$m=65536,t=8,p=2$I57FcJMdwpGTcuOL4Xs4HA$SusoCqS/9adD3+/oKsxPF/6CWNuUKrzOYckmAUZmWNk",
    "print_client_messages" => false,
    "print_server_messages" => false,
    "rank" => 0,
    "restricted_until" => nil,
    "restrictions" => [],
    "roles" => [],
    "shadowbanned" => false,
    "spring_password" => true,
    "steam_id" => nil,
    "verified" => false
  },
  "icon" => " fa-solid fa-user",
  "Caster" => "false",
  "Core" => "false",
  "colour" => "#666666",
  "BAR+" => "false",
  "Engine" => "false",
  "Community team" => "false",
  "Verified" => "false",
  "Streamer" => "false",
  "Mentor" => "false",
  "Moderator" => "false",
  "behaviour_score" => "10000",
  "Server" => "false",
  "Tournament" => "false",
  "Reviewer" => "false",
  "Gameplay" => "false",
  "VIP" => "false",
  "Infrastructure" => "false",
  "email" => "spadsbot@spadsbot.com",
  "trust_score" => "10000",
  "roles" => [],
  "Promo team" => "false",
  "Overwatch" => "false",
  "Data export" => "false",
  "Donor" => "false",
  "Trusted" => "false",
  "Bot" => "true",
  "Admin" => "false",
  "Tester" => "false",
  "social_score" => "0",
  "Academy manager" => "false"
}

We can see that each checkbox is passed as their own attribute. However, the form in (1.) loads loads all the checkbox values from the roles field.

"roles" => [],

e.g.

roles: ["Bot", "Caster", "Mapping", "Mentor", "VIP"]

The fields e.g. ("Bot", "Admin") are not part of the user:

%Teiserver.Account.User{
  __meta__: #Ecto.Schema.Metadata<:loaded, "account_users">,
  id: 28,
  name: "spadsbot[000]",
  email: "spadsbot@spadsbot.com",
  password: "$argon2id$v=19$m=65536,t=8,p=2$I57FcJMdwpGTcuOL4Xs4HA$SusoCqS/9adD3+/oKsxPF/6CWNuUKrzOYckmAUZmWNk",
  icon: " fa-solid fa-user",
  colour: "#666666",
  data: %{
    "bot" => false,
    "chobby_hash" => nil,
    "country" => "??",
    "discord_dm_channel" => nil,
    "discord_dm_channel_id" => nil,
    "discord_id" => nil,
    "email_change_code" => nil,
    "hw_hash" => nil,
    "last_login" => 28609015,
    "last_login_mins" => 28609015,
    "last_login_timex" => "2024-05-24T08:55:12.000625Z",
    "lobby_client" => "SPADS v",
    "lobby_hash" => "57015357 5636bd6e65323f54",
    "moderator" => false,
    "password_hash" => "$argon2id$v=19$m=65536,t=8,p=2$I57FcJMdwpGTcuOL4Xs4HA$SusoCqS/9adD3+/oKsxPF/6CWNuUKrzOYckmAUZmWNk",
    "print_client_messages" => false,
    "print_server_messages" => false,
    "rank" => 0,
    "restricted_until" => nil,
    "restrictions" => [],
    "roles" => [],
    "shadowbanned" => false,
    "spring_password" => true,
    "steam_id" => nil,
    "verified" => false
  },
  roles: [],
  permissions: [],
  restrictions: [],
  restricted_until: nil,
  shadowbanned: false,
  last_login: nil,
  last_login_timex: ~U[2024-05-24 08:55:12Z],
  last_played: nil,
  last_logout: nil,
  discord_id: nil,
  discord_dm_channel_id: nil,
  steam_id: nil,
  user_configs: #Ecto.Association.NotLoaded<association :user_configs is not loaded>,
  clan_id: nil,
  clan: #Ecto.Association.NotLoaded<association :clan is not loaded>,
  smurf_of_id: nil,
  smurf_of: #Ecto.Association.NotLoaded<association :smurf_of is not loaded>,
  user_stat: #Ecto.Association.NotLoaded<association :user_stat is not loaded>,
  behaviour_score: 10000,
  trust_score: 10000,
  social_score: 0,
  inserted_at: ~N[2024-05-24 08:44:35],
  updated_at: ~N[2024-05-24 16:33:05]
}

Possible solution

I made a draft that transforms the attributes and fits them into the roles field, which works and fixes the issue for my setup. (I will link it soon).

However, I am kind of confused why this is not a problem for @jauggy . Maybe there are differences in the versions used.

I used Elixir 1.14.5 and Erlang/OTP 26 [erts-14.2.3] all dependency versions should be the standard ones from the mix.exs file.

jauggy commented 2 months ago

@jere0500 are you saying when you tick the Bot checkbox, save, then return to the user, the bot checkbox is not ticked?

Does it work for the community roles?

Also note that this ticket is specifically for community roles. If you have an issue with the bot role you can make a new ticket.

I'm using this: erlang 25.2.3 elixir 1.14.3-otp-25

jere0500 commented 2 months ago

Yes, edit > ticking boxes > save changes after clicking edit again, no previous ticked checkbox is ticked.

No, it does not work for the Bot checkbox either. In fact, it does not work for any checkbox. Other fields in the form work as expected.

Thanks for the remark I will create a new issue.

I have also tried to do a mix deps.clean --all and retried with your versions, same result.