+ */
+ public function getAllGuestAccounts(?int $limit = null, ?int $offset = null): array {
+ if (!$this->allowListing) {
+ return [];
+ }
+
+ $query = $this->dbConn->getQueryBuilder();
+ $query->select('uid', 'email', 'displayname')
+ ->from('guests_users')
+ ->orderBy('uid_lower', 'ASC')
+ ->setMaxResults($limit)
+ ->setFirstResult($offset);
+
+ $result = $query->executeQuery();
+ $users = [];
+ while ($row = $result->fetch()) {
+ $users[(string)$row['uid']] = [
+ 'email' => (string)$row['email'],
+ 'displayname' => (string)$row['displayname'],
+ ];
+ }
+
+ return $users;
+ }
+
/**
* Check if the password is correct without logging in the user
* returns the user id or false
@@ -238,7 +275,7 @@ public function getDisplayNames($search = '', $limit = null, $offset = null): ar
* @return string|false
*/
public function checkPassword(string $loginName, string $password) {
- if (!str_contains($loginName, '@')) {
+ if (!$this->potentialGuestUserId($loginName)) {
return false;
}
@@ -275,9 +312,13 @@ public function checkPassword(string $loginName, string $password) {
* @param string $uid the username
*/
private function loadUser($uid): bool {
+ if (isset($this->cache[$uid]) && $this->cache[$uid] === false) {
+ return false;
+ }
+
// guests $uid could be NULL or ''
// or is not an email anyway
- if (!str_contains($uid, '@')) {
+ if (!$this->potentialGuestUserId($uid)) {
$this->cache[$uid] = false;
return false;
}
@@ -390,7 +431,7 @@ public function getBackendName(): string {
}
public function getRealUID(string $uid): string {
- if (!str_contains($uid, '@')) {
+ if (!$this->potentialGuestUserId($uid)) {
throw new \RuntimeException($uid . ' does not exist');
}
@@ -404,4 +445,16 @@ public function getRealUID(string $uid): string {
return $this->cache[$uid]['uid'];
}
+
+ /**
+ * Guest app user ids are:
+ * - either email addresses so they need to contain an @
+ * - lowercase sha256 hashes of email addresses, 64 characters of a-f and 0-9
+ *
+ * @param string $userId
+ * @return bool
+ */
+ protected function potentialGuestUserId(string $userId): bool {
+ return str_contains($userId, '@') || preg_match('/^[a-f0-9]{64}$/', $userId);
+ }
}
diff --git a/src/components/GuestList.vue b/src/components/GuestList.vue
index 4615964f..a712337d 100644
--- a/src/components/GuestList.vue
+++ b/src/components/GuestList.vue
@@ -11,6 +11,9 @@
|
{{ t('guests', 'Email') }}
|
+
+ {{ t('guests', 'User ID') }}
+ |
{{ t('guests', 'Name') }}
|
@@ -31,6 +34,10 @@
:title="guest.email">
{{ guest.email }}
+
+ {{ guest.uid }}
+ |
{{ guest.display_name }}
@@ -46,7 +53,7 @@
|
- |
+ |
|
diff --git a/src/views/GuestSettings.vue b/src/views/GuestSettings.vue
index 0fe6045c..3e90301f 100644
--- a/src/views/GuestSettings.vue
+++ b/src/views/GuestSettings.vue
@@ -39,6 +39,12 @@
{{ t('guests', 'Guest accounts can access mounted external storages') }}
+
+ {{ t('guests', 'Use a hash of the email as user ID for improved privacy') }}
+
+
@@ -133,6 +139,7 @@ export default {
config: {
useWhitelist: false,
allowExternalStorage: false,
+ useHashedEmailAsUserID: true,
hideUsers: false,
whitelist: [],
whiteListableApps: [],
diff --git a/tests/unit/Command/AddCommandTest.php b/tests/unit/Command/AddCommandTest.php
index c3fad58d..ca950afb 100644
--- a/tests/unit/Command/AddCommandTest.php
+++ b/tests/unit/Command/AddCommandTest.php
@@ -9,6 +9,7 @@
namespace OCA\Guests\Test\Command\Unit;
use OCA\Guests\Command\AddCommand;
+use OCA\Guests\Config;
use OCA\Guests\GuestManager;
use OCP\IUser;
use OCP\IUserManager;
@@ -19,14 +20,10 @@
use Test\TestCase;
class AddCommandTest extends TestCase {
- /** @var IUserManager|MockObject */
- private $userManager;
-
- /** @var GuestManager|MockObject */
- private $guestManager;
-
- /** @var IMailer|MockObject */
- private $mailer;
+ private IUserManager&MockObject $userManager;
+ private GuestManager&MockObject $guestManager;
+ private IMailer&MockObject $mailer;
+ private Config&MockObject $config;
private ?AddCommand $command = null;
@@ -38,11 +35,13 @@ protected function setUp(): void {
$this->userManager = $this->createMock(IUserManager::class);
$this->guestManager = $this->createMock(GuestManager::class);
$this->mailer = $this->createMock(IMailer::class);
+ $this->config = $this->createMock(Config::class);
$this->command = new AddCommand(
$this->userManager,
$this->mailer,
- $this->guestManager
+ $this->guestManager,
+ $this->config,
);
$this->command->setApplication(new Application());
diff --git a/tests/unit/Migration/OwncloudGuestMigrationTest.php b/tests/unit/Migration/OwncloudGuestMigrationTest.php
index 9e742cc1..0b872b78 100644
--- a/tests/unit/Migration/OwncloudGuestMigrationTest.php
+++ b/tests/unit/Migration/OwncloudGuestMigrationTest.php
@@ -45,6 +45,7 @@ protected function setUp():void {
}
private function createOcGuest(string $userId): void {
+ $this->userManager->get($userId)?->delete();
$this->userManager->createUser($userId, $userId . '_password');
$this->config->setUserValue($userId, 'owncloud', 'isGuest', '1');
}