Skip to content
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

feat: add pronouns to account profile #44013

Merged
merged 2 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/provisioning_api/lib/Controller/AUserData.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ protected function getUserData(string $userId, bool $includeScopes = false): ?ar
IAccountManager::PROPERTY_HEADLINE,
IAccountManager::PROPERTY_BIOGRAPHY,
IAccountManager::PROPERTY_PROFILE_ENABLED,
IAccountManager::PROPERTY_PRONOUNS,
Fixed Show fixed Hide fixed
] as $propertyName) {
$property = $userAccount->getProperty($propertyName);
$data[$propertyName] = $property->getValue();
Expand Down
8 changes: 7 additions & 1 deletion apps/provisioning_api/lib/Controller/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ public function getEditableFieldsForUser(string $userId): DataResponse {
$permittedFields[] = IAccountManager::PROPERTY_HEADLINE;
$permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY;
$permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED;
$permittedFields[] = IAccountManager::PROPERTY_PRONOUNS;
Fixed Show fixed Hide fixed

return new DataResponse($permittedFields);
}
Expand Down Expand Up @@ -944,6 +945,8 @@ public function editUser(string $userId, string $key, string $value): DataRespon
$permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY;
$permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED;
$permittedFields[] = IAccountManager::PROPERTY_BIRTHDATE;
$permittedFields[] = IAccountManager::PROPERTY_PRONOUNS;
Fixed Show fixed Hide fixed

$permittedFields[] = IAccountManager::PROPERTY_PHONE . self::SCOPE_SUFFIX;
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX;
$permittedFields[] = IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX;
Expand All @@ -955,8 +958,8 @@ public function editUser(string $userId, string $key, string $value): DataRespon
$permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY . self::SCOPE_SUFFIX;
$permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED . self::SCOPE_SUFFIX;
$permittedFields[] = IAccountManager::PROPERTY_BIRTHDATE . self::SCOPE_SUFFIX;

$permittedFields[] = IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX;
$permittedFields[] = IAccountManager::PROPERTY_PRONOUNS . self::SCOPE_SUFFIX;

// If admin they can edit their own quota and manager
$isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID());
Expand Down Expand Up @@ -997,6 +1000,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon
$permittedFields[] = IAccountManager::PROPERTY_HEADLINE;
$permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY;
$permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED;
$permittedFields[] = IAccountManager::PROPERTY_PRONOUNS;
$permittedFields[] = self::USER_FIELD_QUOTA;
$permittedFields[] = self::USER_FIELD_NOTIFICATION_EMAIL;
$permittedFields[] = self::USER_FIELD_MANAGER;
Expand Down Expand Up @@ -1141,6 +1145,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon
case IAccountManager::PROPERTY_HEADLINE:
case IAccountManager::PROPERTY_BIOGRAPHY:
case IAccountManager::PROPERTY_BIRTHDATE:
case IAccountManager::PROPERTY_PRONOUNS:
Fixed Show fixed Hide fixed
$userAccount = $this->accountManager->getAccount($targetUser);
try {
$userProperty = $userAccount->getProperty($key);
Expand Down Expand Up @@ -1189,6 +1194,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon
case IAccountManager::PROPERTY_PROFILE_ENABLED . self::SCOPE_SUFFIX:
case IAccountManager::PROPERTY_BIRTHDATE . self::SCOPE_SUFFIX:
case IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX:
case IAccountManager::PROPERTY_PRONOUNS . self::SCOPE_SUFFIX:
Fixed Show fixed Hide fixed
$propertyName = substr($key, 0, strlen($key) - strlen(self::SCOPE_SUFFIX));
$userAccount = $this->accountManager->getAccount($targetUser);
$userProperty = $userAccount->getProperty($propertyName);
Expand Down
2 changes: 2 additions & 0 deletions apps/provisioning_api/lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
* phoneScope?: Provisioning_APIUserDetailsScope,
* profile_enabled: string,
* profile_enabledScope?: Provisioning_APIUserDetailsScope,
* pronouns: string,
* pronounsScope?: Provisioning_APIUserDetailsScope,
* quota: Provisioning_APIUserDetailsQuota,
* role: string,
* roleScope?: Provisioning_APIUserDetailsScope,
Expand Down
7 changes: 7 additions & 0 deletions apps/provisioning_api/openapi-administration.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"organisation",
"phone",
"profile_enabled",
"pronouns",
"quota",
"role",
"subadmin",
Expand Down Expand Up @@ -226,6 +227,12 @@
"profile_enabledScope": {
"$ref": "#/components/schemas/UserDetailsScope"
},
"pronouns": {
"type": "string"
},
"pronounsScope": {
"$ref": "#/components/schemas/UserDetailsScope"
},
"quota": {
"$ref": "#/components/schemas/UserDetailsQuota"
},
Expand Down
7 changes: 7 additions & 0 deletions apps/provisioning_api/openapi-full.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
"organisation",
"phone",
"profile_enabled",
"pronouns",
"quota",
"role",
"subadmin",
Expand Down Expand Up @@ -273,6 +274,12 @@
"profile_enabledScope": {
"$ref": "#/components/schemas/UserDetailsScope"
},
"pronouns": {
"type": "string"
},
"pronounsScope": {
"$ref": "#/components/schemas/UserDetailsScope"
},
"quota": {
"$ref": "#/components/schemas/UserDetailsQuota"
},
Expand Down
7 changes: 7 additions & 0 deletions apps/provisioning_api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
"organisation",
"phone",
"profile_enabled",
"pronouns",
"quota",
"role",
"subadmin",
Expand Down Expand Up @@ -273,6 +274,12 @@
"profile_enabledScope": {
"$ref": "#/components/schemas/UserDetailsScope"
},
"pronouns": {
"type": "string"
},
"pronounsScope": {
"$ref": "#/components/schemas/UserDetailsScope"
},
"quota": {
"$ref": "#/components/schemas/UserDetailsQuota"
},
Expand Down
18 changes: 16 additions & 2 deletions apps/provisioning_api/tests/Controller/UsersControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,7 @@ public function testGetUserDataAsAdmin(): void {
IAccountManager::PROPERTY_HEADLINE => ['value' => 'headline'],
IAccountManager::PROPERTY_BIOGRAPHY => ['value' => 'biography'],
IAccountManager::PROPERTY_PROFILE_ENABLED => ['value' => '1'],
IAccountManager::PROPERTY_PRONOUNS => ['value' => 'they/them'],
]);
$this->config
->method('getUserValue')
Expand Down Expand Up @@ -1068,6 +1069,7 @@ public function testGetUserDataAsAdmin(): void {
'profile_enabled' => '1',
'notify_email' => null,
'manager' => '',
'pronouns' => 'they/them',
];
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
}
Expand Down Expand Up @@ -1171,6 +1173,7 @@ public function testGetUserDataAsSubAdminAndUserIsAccessible(): void {
IAccountManager::PROPERTY_HEADLINE => ['value' => 'headline'],
IAccountManager::PROPERTY_BIOGRAPHY => ['value' => 'biography'],
IAccountManager::PROPERTY_PROFILE_ENABLED => ['value' => '1'],
IAccountManager::PROPERTY_PRONOUNS => ['value' => 'they/them'],
]);

$this->l10nFactory
Expand Down Expand Up @@ -1209,6 +1212,7 @@ public function testGetUserDataAsSubAdminAndUserIsAccessible(): void {
'profile_enabled' => '1',
'notify_email' => null,
'manager' => '',
'pronouns' => 'they/them',
];
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
}
Expand Down Expand Up @@ -1351,6 +1355,7 @@ public function testGetUserDataAsSubAdminSelfLookup(): void {
IAccountManager::PROPERTY_HEADLINE => ['value' => 'headline'],
IAccountManager::PROPERTY_BIOGRAPHY => ['value' => 'biography'],
IAccountManager::PROPERTY_PROFILE_ENABLED => ['value' => '1'],
IAccountManager::PROPERTY_PRONOUNS => ['value' => 'they/them'],
]);

$this->l10nFactory
Expand Down Expand Up @@ -1388,6 +1393,7 @@ public function testGetUserDataAsSubAdminSelfLookup(): void {
'profile_enabled' => '1',
'notify_email' => null,
'manager' => '',
'pronouns' => 'they/them',
];
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
}
Expand Down Expand Up @@ -1729,6 +1735,7 @@ public function selfEditChangePropertyProvider() {
[IAccountManager::PROPERTY_HEADLINE, 'Hi', 'Hello'],
[IAccountManager::PROPERTY_BIOGRAPHY, 'A biography', 'Another biography'],
[IAccountManager::PROPERTY_PROFILE_ENABLED, '1', '0'],
[IAccountManager::PROPERTY_PRONOUNS, 'they/them', 'he/him'],
];
}

Expand Down Expand Up @@ -1806,6 +1813,7 @@ public function selfEditChangePropertyScopeProvider() {
[IAccountManager::PROPERTY_HEADLINE, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED],
[IAccountManager::PROPERTY_BIOGRAPHY, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED],
[IAccountManager::PROPERTY_PROFILE_ENABLED, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED],
[IAccountManager::PROPERTY_PRONOUNS, IAccountManager::SCOPE_LOCAL, IAccountManager::SCOPE_FEDERATED],
];
}

Expand Down Expand Up @@ -3690,7 +3698,8 @@ public function testGetCurrentUserLoggedIn(): void {
'role' => 'role',
'headline' => 'headline',
'biography' => 'biography',
'profile_enabled' => '1'
'profile_enabled' => '1',
'pronouns' => 'they/them',
]
);

Expand All @@ -3711,6 +3720,7 @@ public function testGetCurrentUserLoggedIn(): void {
'headline' => 'headline',
'biography' => 'biography',
'profile_enabled' => '1',
'pronouns' => 'they/them',
];

$this->assertSame($expected, $api->getCurrentUser()->getData());
Expand Down Expand Up @@ -3775,7 +3785,8 @@ public function testGetUser(): void {
'role' => 'role',
'headline' => 'headline',
'biography' => 'biography',
'profile_enabled' => '1'
'profile_enabled' => '1',
'pronouns' => 'they/them',
];

$api->expects($this->exactly(2))
Expand Down Expand Up @@ -4115,6 +4126,7 @@ public function dataGetEditableFields() {
IAccountManager::PROPERTY_HEADLINE,
IAccountManager::PROPERTY_BIOGRAPHY,
IAccountManager::PROPERTY_PROFILE_ENABLED,
IAccountManager::PROPERTY_PRONOUNS,
]],
[true, ISetDisplayNameBackend::class, [
IAccountManager::PROPERTY_DISPLAYNAME,
Expand All @@ -4130,6 +4142,7 @@ public function dataGetEditableFields() {
IAccountManager::PROPERTY_HEADLINE,
IAccountManager::PROPERTY_BIOGRAPHY,
IAccountManager::PROPERTY_PROFILE_ENABLED,
IAccountManager::PROPERTY_PRONOUNS,
]],
[true, UserInterface::class, [
IAccountManager::PROPERTY_EMAIL,
Expand All @@ -4144,6 +4157,7 @@ public function dataGetEditableFields() {
IAccountManager::PROPERTY_HEADLINE,
IAccountManager::PROPERTY_BIOGRAPHY,
IAccountManager::PROPERTY_PROFILE_ENABLED,
IAccountManager::PROPERTY_PRONOUNS,
]],
];
}
Expand Down
5 changes: 5 additions & 0 deletions apps/settings/lib/Controller/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ public function setUserSettings(?string $avatarScope = null,
?string $fediverseScope = null,
?string $birthdate = null,
?string $birthdateScope = null,
?string $pronouns = null,
?string $pronounsScope = null
) {
$user = $this->userSession->getUser();
if (!$user instanceof IUser) {
Expand Down Expand Up @@ -375,6 +377,7 @@ public function setUserSettings(?string $avatarScope = null,
IAccountManager::PROPERTY_TWITTER => ['value' => $twitter, 'scope' => $twitterScope],
IAccountManager::PROPERTY_FEDIVERSE => ['value' => $fediverse, 'scope' => $fediverseScope],
IAccountManager::PROPERTY_BIRTHDATE => ['value' => $birthdate, 'scope' => $birthdateScope],
IAccountManager::PROPERTY_PRONOUNS => ['value' => $pronouns, 'scope' => $pronounsScope],
];
$allowUserToChangeDisplayName = $this->config->getSystemValueBool('allow_user_to_change_display_name', true);
foreach ($updatable as $property => $data) {
Expand Down Expand Up @@ -418,6 +421,8 @@ public function setUserSettings(?string $avatarScope = null,
'fediverseScope' => $userAccount->getProperty(IAccountManager::PROPERTY_FEDIVERSE)->getScope(),
'birthdate' => $userAccount->getProperty(IAccountManager::PROPERTY_BIRTHDATE)->getValue(),
'birthdateScope' => $userAccount->getProperty(IAccountManager::PROPERTY_BIRTHDATE)->getScope(),
'pronouns' => $userAccount->getProperty(IAccountManager::PROPERTY_PRONOUNS)->getValue(),
'pronounsScope' => $userAccount->getProperty(IAccountManager::PROPERTY_PRONOUNS)->getScope(),
'message' => $this->l10n->t('Settings saved'),
],
],
Expand Down
1 change: 1 addition & 0 deletions apps/settings/lib/Settings/Personal/PersonalInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ public function getForm(): TemplateResponse {
'biography' => $this->getProperty($account, IAccountManager::PROPERTY_BIOGRAPHY),
'birthdate' => $this->getProperty($account, IAccountManager::PROPERTY_BIRTHDATE),
'firstDayOfWeek' => $this->config->getUserValue($uid, 'core', AUserData::USER_FIELD_FIRST_DAY_OF_WEEK),
'pronouns' => $this->getProperty($account, IAccountManager::PROPERTY_PRONOUNS),
Fixed Show fixed Hide fixed
];

$accountParameters = [
Expand Down
45 changes: 45 additions & 0 deletions apps/settings/src/components/PersonalInfo/PronounsSection.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!--
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
<AccountPropertySection v-bind.sync="pronouns"
:placeholder="randomPronounsPlaceholder" />
</template>

<script>
import { loadState } from '@nextcloud/initial-state'

import AccountPropertySection from './shared/AccountPropertySection.vue'

import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js'

const { pronouns } = loadState('settings', 'personalInfoParameters', {})

export default {
name: 'PronounsSection',

components: {
AccountPropertySection,
},

data() {
return {
pronouns: { ...pronouns, readable: NAME_READABLE_ENUM[pronouns.name] },
}
},

computed: {
randomPronounsPlaceholder() {
const pronouns = [
this.t('settings', 'she/her'),
this.t('settings', 'he/him'),
this.t('settings', 'they/them'),
]
const pronounsExample = pronouns[Math.floor(Math.random() * pronouns.length)]
return this.t('settings', `Your pronouns. E.g. ${pronounsExample}`, { pronounsExample })
},
},
}
</script>
13 changes: 9 additions & 4 deletions apps/settings/src/constants/AccountPropertyConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,40 @@ export const ACCOUNT_PROPERTY_ENUM = Object.freeze({
ADDRESS: 'address',
AVATAR: 'avatar',
BIOGRAPHY: 'biography',
BIRTHDATE: 'birthdate',
DISPLAYNAME: 'displayname',
EMAIL_COLLECTION: 'additional_mail',
EMAIL: 'email',
FEDIVERSE: 'fediverse',
HEADLINE: 'headline',
NOTIFICATION_EMAIL: 'notify_email',
FEDIVERSE: 'fediverse',
ORGANISATION: 'organisation',
PHONE: 'phone',
PROFILE_ENABLED: 'profile_enabled',
PRONOUNS: 'pronouns',
ROLE: 'role',
TWITTER: 'twitter',
WEBSITE: 'website',
BIRTHDATE: 'birthdate',
})

/** Enum of account properties to human readable account property names */
export const ACCOUNT_PROPERTY_READABLE_ENUM = Object.freeze({
ADDRESS: t('settings', 'Location'),
AVATAR: t('settings', 'Profile picture'),
BIOGRAPHY: t('settings', 'About'),
BIRTHDATE: t('settings', 'Date of birth'),
DISPLAYNAME: t('settings', 'Full name'),
EMAIL_COLLECTION: t('settings', 'Additional email'),
EMAIL: t('settings', 'Email'),
FEDIVERSE: t('settings', 'Fediverse (e.g. Mastodon)'),
HEADLINE: t('settings', 'Headline'),
ORGANISATION: t('settings', 'Organisation'),
PHONE: t('settings', 'Phone number'),
PROFILE_ENABLED: t('settings', 'Profile'),
PRONOUNS: t('settings', 'Pronouns'),
ROLE: t('settings', 'Role'),
TWITTER: t('settings', 'X (formerly Twitter)'),
FEDIVERSE: t('settings', 'Fediverse (e.g. Mastodon)'),
WEBSITE: t('settings', 'Website'),
BIRTHDATE: t('settings', 'Date of birth'),
})

export const NAME_READABLE_ENUM = Object.freeze({
Expand All @@ -65,6 +67,7 @@ export const NAME_READABLE_ENUM = Object.freeze({
[ACCOUNT_PROPERTY_ENUM.FEDIVERSE]: ACCOUNT_PROPERTY_READABLE_ENUM.FEDIVERSE,
[ACCOUNT_PROPERTY_ENUM.WEBSITE]: ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE,
[ACCOUNT_PROPERTY_ENUM.BIRTHDATE]: ACCOUNT_PROPERTY_READABLE_ENUM.BIRTHDATE,
[ACCOUNT_PROPERTY_ENUM.PRONOUNS]: ACCOUNT_PROPERTY_READABLE_ENUM.PRONOUNS,
})

/** Enum of profile specific sections to human readable names */
Expand All @@ -89,6 +92,7 @@ export const PROPERTY_READABLE_KEYS_ENUM = Object.freeze({
[ACCOUNT_PROPERTY_READABLE_ENUM.FEDIVERSE]: ACCOUNT_PROPERTY_ENUM.FEDIVERSE,
[ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE]: ACCOUNT_PROPERTY_ENUM.WEBSITE,
[ACCOUNT_PROPERTY_READABLE_ENUM.BIRTHDATE]: ACCOUNT_PROPERTY_ENUM.BIRTHDATE,
[ACCOUNT_PROPERTY_READABLE_ENUM.PRONOUNS]: ACCOUNT_PROPERTY_ENUM.PRONOUNS,
})

/**
Expand Down Expand Up @@ -134,6 +138,7 @@ export const PROPERTY_READABLE_SUPPORTED_SCOPES_ENUM = Object.freeze({
[ACCOUNT_PROPERTY_READABLE_ENUM.FEDIVERSE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],
[ACCOUNT_PROPERTY_READABLE_ENUM.WEBSITE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],
[ACCOUNT_PROPERTY_READABLE_ENUM.BIRTHDATE]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],
[ACCOUNT_PROPERTY_READABLE_ENUM.PRONOUNS]: [SCOPE_ENUM.LOCAL, SCOPE_ENUM.PRIVATE],
})

/** List of readable account properties which aren't published to the lookup server */
Expand Down
Loading
Loading