Skip to content

fix(api): seperate and fix user add and update endpoint logic #3040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

LuukBlankenstijn
Copy link

@LuukBlankenstijn LuukBlankenstijn commented Jul 20, 2025

Found some bugs while using the API, and since I need the endpoints, fixed them.

Problem I encountered:
Endpoint /api/v4/users/{id} PUT request returned{ 400, Body data exceeded php.ini's 'post_max_size' directive (currently set to 512M)}.
Could not get it to work whatever I tried. When looking at the code I also discovered some other issues in the case of updating the user with App\Controller\API\UserController.php addOrUpdateUser().
What I did is changing the content type of the api-doc attribute to application/json, and separated the add and update method in to dedicated methods. I realize this is a breaking change in the api spec and not ideal.

I got the errors on both the DOMjudge instance running on the GEHACK server in Eindhoven, and my own local instance.

This exception is generated in App\EventListener\BodyToBigListener.php. This happens because the amount of parameters on the request is 0. (I get this even when using /api/doc on a running domjudge instance). I first tried fixing the request, but could not get it to work. Because it made more sense to me for a request like this to accept json instead of formdata I decided to change it to that. After I did this the request now worked, but i found some flaws in the update logic for user.

For example: name, username and id are required to even make an update by the documentation. I would have expected to just need an id and being able to update any field. Then, on line 150 in App\Controller\Api\Usercontroler:

protected function addOrUpdateUser(AddUser $addUser, Request $request): Response
    {
        if ($addUser instanceof UpdateUser && !$addUser->id) {
            throw new BadRequestHttpException('`id` field is required');
        }

        if ($this->em->getRepository(User::class)->findOneBy(['username' => $addUser->username])) {
            throw new BadRequestHttpException(sprintf("User %s already exists", $addUser->username));
        }
        $user = new User();
              if ($addUser instanceof UpdateUser) {
                  $existingUser = $this->em->getRepository(User::class)->findOneBy(['externalid' => $addUser->id]);
                  if ($existingUser) {
                      $user = $existingUser;
                  }
              }

        $user
            ->setUsername($addUser->username)
            ->setName($addUser->name)
            ->setEmail($addUser->email)
            ->setIpAddress($addUser->ip)
            ->setPlainPassword($addUser->password)
            ->setEnabled($addUser->enabled ?? true);

       // rest of method
}

So if the user already exists we get a BadRequestException. This effectively means that for every update we want to do to a user, the username has to be changed.
Then also we cannot do partial update by leaving fields in the request null, since all properties of the UpdateUser dto are assigned to the existing user, even when null.

@LuukBlankenstijn LuukBlankenstijn marked this pull request as ready for review July 20, 2025 10:06
@vmcj
Copy link
Member

vmcj commented Jul 20, 2025

Can you explain which problem you encountered?

@LuukBlankenstijn LuukBlankenstijn marked this pull request as draft July 20, 2025 10:42
@LuukBlankenstijn
Copy link
Author

Updated the description

@vmcj
Copy link
Member

vmcj commented Jul 20, 2025

Found some bugs while using the API, and since I need the endpoints, fixed them.

Problem I encountered: Endpoint /api/v4/users/{id} PUT request returned{ 400, Body data exceeded php.ini's 'post_max_size' directive (currently set to 512M)}.

Let's discuss in Slack how to fix this one, I assume you posted something which is larger than 512M? Did you raise the post_max_size? You can check for the value detected in the config checker.

... When looking at the code I also discovered some other issues in the case of updating the user with App\Controller\API\UserController.php addOrUpdateUser(). What I did is changing the content type of the api-doc attribute to application/json,

I can see that you did this, but I'm not sure yet why it wants a form but I suspect this is legacy.

and separated the add and update method in to dedicated methods. I realize this is a breaking change in the api spec and not ideal.

So we're working on a major release so now would be the time to make such choices but let's see if we can prevent it still.

@@ -291,12 +291,12 @@ public function singleAction(Request $request, string $id): Response
* Add a new user.
*/
#[IsGranted('ROLE_API_WRITER')]
#[Rest\Post]
#[Rest\Put("")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to also allow PUT here, but dropping POST doesn't make sense to me.

@@ -8,10 +8,9 @@
#[OA\Schema(required: ['username', 'name', 'roles'])]
class AddUser
{
/**
* @param array<string> $roles
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHPstan does not agree with removing this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sorry, I forgot to run PHPstan

@vmcj
Copy link
Member

vmcj commented Jul 20, 2025

@LuukBlankenstijn can you provide the files you were using which hit this error?

@eldering
Copy link
Member

I've not looked into the changes in detail (and I guess @nickygerritsen might be a better reviewer), but from the description it's not clear to me what these changes are fixing and why/how. Because this seems to have nothing to do with a maximum post size of a request. Can you clarify that?

@LuukBlankenstijn
Copy link
Author

I updated the description again, I'm sorry for lack initial lack of explanation

@nickygerritsen
Copy link
Member

I think we can do something smart to still have both update and create in one action, will think about it.

Although that is not very REST, so maybe we shouldn't?

As form json vs formdata, ideally it'd accept both, so I will investigate if we can get that to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants