Skip to content

feat(user-management): add “Add existing account” dialog and provisio… #53114

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

cushdog
Copy link

@cushdog cushdog commented May 26, 2025

Summary

This PR adds two related features:

  1. Frontend

    • A new “Add existing account” button in the User Management navigation.
    • A modal dialog (AddExistingUserDialog.vue) that lets group-admins search for existing users and assign them to the currently selected group.
    • Vuex state (showAddExistingUserForm) persisted alongside the “New account” form flag to open/close the dialog.
  2. Backend

    • A new Provisioning API endpoint:
      GET /ocs/v2.php/cloud/users/search?search=<query>
      
      Returns a JSON map of userId => displayName for all Nextcloud users matching the search string.
    • Access restricted to admins, delegated admins, and subadmins (throws 403 otherwise).

Screenshots

BeforeAfter
Before Image After

TODO

  • Unit tests
    • Frontend: tests for AddExistingUserDialog.vue (rendering, search behavior, submit).
    • Backend: tests for UsersController::searchAllUsers() (success and 403 cases).
  • Integration/API tests for the new /users/search endpoint.
  • Screenshots (before/after) of the new “Add existing account” button and dialog.
  • Documentation
    • Update the Admin Manual / Provisioning API docs to include /users/search.
    • Add a note in the “Groups” section of the User docs about this UI change.
  • Backport request to the 32 and 31 branches if this lands post-release.

Checklist

  • Code is properly formatted
  • All commits carry a valid DCO sign-off
  • Tests (unit, integration, API) are included
  • Screenshots before/after for front-end changes
  • Documentation (manuals or wiki) updated or noted “not required”
  • Backports requested for stable branches where applicable

Note

I just wanted to quickly note that I didn't update the documentation yet, since I wasn't sure if that should only be updated after this pull-request is potentially accepted!

@cushdog cushdog requested review from provokateurin and a team as code owners May 26, 2025 06:52
@cushdog cushdog requested review from ArtificialOwl, skjnldsv, susnux and artonge and removed request for a team May 26, 2025 06:52
@@ -25,31 +25,32 @@
['root' => '/cloud', 'name' => 'Groups#deleteGroup', 'url' => '/groups/{groupId}', 'verb' => 'DELETE', 'requirements' => ['groupId' => '.+']],

// Users
['root' => '/cloud', 'name' => 'Users#getUsers', 'url' => '/users', 'verb' => 'GET'],
Copy link
Member

Choose a reason for hiding this comment

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

Can you run composer run cs:fix locally?

Copy link
Author

Choose a reason for hiding this comment

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

Done! Thanks for the catch!

Copy link
Member

Choose a reason for hiding this comment

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

Hmpf the reformating is still there

* 200: Users returned
*/
#[NoAdminRequired]
public function searchAllUsers(string $search = '', ?int $limit = null, int $offset = 0): DataResponse {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this not exactly what getUsers does? It also has a search param

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah there is no need for a new endpoint, the frontend should use the existing ones unless there’s a really good reason.
I think getUsersDetails is the one to use as displaynames are needed, I suppose this is what the rest of the frontend uses (I did not check).

Copy link
Author

Choose a reason for hiding this comment

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

Sorry about this! Changed this and did a much simpler version of what I had before, let me know what you think now!

</template>

<script>
import { translate as t } from '@nextcloud/l10n'
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
import { translate as t } from '@nextcloud/l10n'
import { t } from '@nextcloud/l10n'

Copy link
Author

Choose a reason for hiding this comment

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

Fixed!

</NcDialog>
</template>

<script>
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer new files to be Typescript.

Suggested change
<script>
<script lang="ts">

(and then use defineComponent below)

Copy link
Author

Choose a reason for hiding this comment

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

Also fixed!

<template #icon>
<NcIconSvgWrapper :path="mdiCog" />
</template>
{{ t('settings', 'Account management settings') }}
{{ t("settings", "Account management settings") }}
Copy link
Contributor

Choose a reason for hiding this comment

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

we use single quotes

Copy link
Author

Choose a reason for hiding this comment

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

Noted and fixed!

Copy link
Contributor

Choose a reason for hiding this comment

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

please use npm run lint:fix locally. This contains a lot of fixable issues like usage of semicolon or double quotes.

Copy link
Author

Choose a reason for hiding this comment

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

Done!

@sorbaugh
Copy link
Contributor

@cushdog for ease of reviewing, can you re-upload the screenshots directly to Github?

Here is a nice example of how you can add the Before/After screenshots: #52423

Thanks again for the PR!

@cushdog cushdog force-pushed the feat/11334-account-endpoint branch from 4e16a51 to 66091a4 Compare May 27, 2025 07:04
@cushdog cushdog requested a review from a team as a code owner May 27, 2025 07:04
@cushdog
Copy link
Author

cushdog commented May 27, 2025

Note: just wanted to quickly apologize for the change in commit history, ran into a bit of git trouble that I was able to work out with a force commit!

@@ -116,7 +116,7 @@ public function getUsers(string $search = '', ?int $limit = null, int $offset =
$subAdminManager = $this->groupManager->getSubAdmin();
$isAdmin = $this->groupManager->isAdmin($uid);
$isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($uid);
if ($isAdmin || $isDelegatedAdmin) {
if ($isAdmin || $isDelegatedAdmin || $subAdminManager->isSubAdmin($user)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This allows group admins to see all users.
@sorbaugh What is the design decision on this? It will be enabled by default? It is a big change.

The linked issue talks about limiting to displayname and a few things, which is not done here, but not sure it would be enough. We might want to safe guard behind an opt-in config flag, at least for upgrades.

Copy link
Contributor

Choose a reason for hiding this comment

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

User iteration is not in our threat model, thus not a problem.
What is a problem is that more information as uid and displayname might be available.

Then again this is not a problem, because if we accept this feature, then every group admin can assign users to their group gaining full admin access over them.
So this means a group admin then has the same permissions on user management as admins, as there are not restrictions anymore (they can just add a user to their group and then adjust the user as they like).

For this its good to have approval of @nickvergessen for security point of view.

Copy link
Member

Choose a reason for hiding this comment

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

So, the API already allows some extend of it.
Using http requests I as able, as a group admin, to add some users to my groups.

I am not sure why we need to change the API 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

We need to change the API so that group admins can list all users, to be able to chose which ones they want to add to their groups

Copy link
Author

Choose a reason for hiding this comment

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

Is the consensus that I would need to change the API then? I couldn't see any way to go about listing all users without adding in some new endpoint that only group-admins could access, which is why my original commit included a change to the API routes.

Copy link
Member

Choose a reason for hiding this comment

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

We need to change the API so that group admins can list all users, to be able to chose which ones they want to add to their group

Right, so only the listing API needs a change. Other than that it should be working already.

Copy link
Author

Choose a reason for hiding this comment

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

My thoughts exactly, I'll revert back to the API-change approach I committed originally!

.htaccess Outdated
Comment on lines 126 to 129
#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####

ErrorDocument 403 /index.php/error/403
ErrorDocument 404 /index.php/error/404
Copy link
Contributor

Choose a reason for hiding this comment

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

Should not be commited

Comment on lines 28 to 30
['root' => '/cloud', 'name' => 'Users#getUsers', 'url' => '/users', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#getUsersDetails', 'url' => '/users/details', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#getDisabledUsersDetails', 'url' => '/users/disabled', 'verb' => 'GET'],
Copy link
Contributor

Choose a reason for hiding this comment

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

Please reset this file space changes and only commit it if there are real changes.

@@ -313,7 +313,6 @@
"Architecture" : "Architektura",
"64-bit" : "64bit",
"It seems like you are running a 32-bit PHP version. Nextcloud needs 64-bit to run well. Please upgrade your OS and PHP to 64-bit!" : "Zdá se, že provozujete 32bitovou verzi PHP. Aby správně fungoval, potřebuje Nextcloud 64bit. Přejděte na 64bit instalaci operačního systému a PHP!",
"Task Processing pickup speed" : "Rychlost vyzvedávání zpracovávání úkolů",
Copy link
Contributor

Choose a reason for hiding this comment

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

All these l10n diff seems unrelated, or did I miss something?

Copy link
Author

Choose a reason for hiding this comment

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

I never actually added these to my changes but they were committed anyways for some reason, I'll see if I can't fix this.

openapi.json Outdated
@@ -25242,6 +25242,104 @@
}
}
},
"/ocs/v2.php/cloud/users/search": {
Copy link
Contributor

Choose a reason for hiding this comment

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

openapi.json should be regenerated now that the new route is gone.

@cushdog
Copy link
Author

cushdog commented May 29, 2025

Apologies, working right now on unstaging the huge amount of extra files that got added in for some reason

@cushdog cushdog force-pushed the feat/11334-account-endpoint branch 4 times, most recently from c26dd3b to 64731fe Compare May 29, 2025 05:59
@cushdog cushdog force-pushed the feat/11334-account-endpoint branch from 64731fe to 1f8e6c6 Compare May 29, 2025 06:20
@cushdog
Copy link
Author

cushdog commented May 29, 2025

Apologies, working right now on unstaging the huge amount of extra files that got added in for some reason

Ok I think I figured this out, apologies I had to do quite a few git operations I wasn't familiar with!

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

Successfully merging this pull request may close these issues.

Groups: Allow group admins to assign existing users
7 participants