aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/l10n/es.js7
-rw-r--r--lib/l10n/es.json7
-rw-r--r--lib/private/Accounts/AccountManager.php58
-rw-r--r--lib/private/AppFramework/App.php32
-rw-r--r--lib/private/AppFramework/DependencyInjection/DIContainer.php4
-rw-r--r--lib/private/AppFramework/Utility/SimpleContainer.php4
-rw-r--r--lib/private/DB/Connection.php9
-rw-r--r--lib/private/DB/ConnectionAdapter.php6
-rw-r--r--lib/private/DB/QueryBuilder/QueryBuilder.php2
-rw-r--r--lib/private/Profile/Actions/BlueskyAction.php65
-rw-r--r--lib/private/Profile/ProfileManager.php2
-rw-r--r--lib/public/Accounts/IAccountManager.php7
-rw-r--r--lib/public/IDBConnection.php13
-rw-r--r--lib/public/Profile/IProfileManager.php1
16 files changed, 183 insertions, 36 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index fda8798fe43..ab0f12233d4 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -1904,6 +1904,7 @@ return array(
'OC\\Preview\\WatcherConnector' => $baseDir . '/lib/private/Preview/WatcherConnector.php',
'OC\\Preview\\WebP' => $baseDir . '/lib/private/Preview/WebP.php',
'OC\\Preview\\XBitmap' => $baseDir . '/lib/private/Preview/XBitmap.php',
+ 'OC\\Profile\\Actions\\BlueskyAction' => $baseDir . '/lib/private/Profile/Actions/BlueskyAction.php',
'OC\\Profile\\Actions\\EmailAction' => $baseDir . '/lib/private/Profile/Actions/EmailAction.php',
'OC\\Profile\\Actions\\FediverseAction' => $baseDir . '/lib/private/Profile/Actions/FediverseAction.php',
'OC\\Profile\\Actions\\PhoneAction' => $baseDir . '/lib/private/Profile/Actions/PhoneAction.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 69e3c41284b..3d32ee7e567 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -1945,6 +1945,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Preview\\WatcherConnector' => __DIR__ . '/../../..' . '/lib/private/Preview/WatcherConnector.php',
'OC\\Preview\\WebP' => __DIR__ . '/../../..' . '/lib/private/Preview/WebP.php',
'OC\\Preview\\XBitmap' => __DIR__ . '/../../..' . '/lib/private/Preview/XBitmap.php',
+ 'OC\\Profile\\Actions\\BlueskyAction' => __DIR__ . '/../../..' . '/lib/private/Profile/Actions/BlueskyAction.php',
'OC\\Profile\\Actions\\EmailAction' => __DIR__ . '/../../..' . '/lib/private/Profile/Actions/EmailAction.php',
'OC\\Profile\\Actions\\FediverseAction' => __DIR__ . '/../../..' . '/lib/private/Profile/Actions/FediverseAction.php',
'OC\\Profile\\Actions\\PhoneAction' => __DIR__ . '/../../..' . '/lib/private/Profile/Actions/PhoneAction.php',
diff --git a/lib/l10n/es.js b/lib/l10n/es.js
index 9c7ea8f5f41..a01ed7e43b8 100644
--- a/lib/l10n/es.js
+++ b/lib/l10n/es.js
@@ -275,6 +275,7 @@ OC.L10N.register(
"A valid Login must be provided" : "Se debe proporcionar un usuario válido",
"Login contains whitespace at the beginning or at the end" : "El usuario contiene espacios en blanco al inicio o al final",
"Login must not consist of dots only" : "El usuario no debe consistir sólo de puntos",
+ "Username is too long" : "El nombre de usuario es demasiado largo",
"Login is invalid because files already exist for this user" : "El nombre de inicio de sesión es inválido porque ya existen archivos para este usuario",
"Account disabled" : "Cuenta deshabilitada",
"Login canceled by app" : "Login cancelado por la app",
@@ -328,13 +329,17 @@ OC.L10N.register(
"Images" : "Imágenes",
"Images to ask a question about" : "Imágenes sobre las cuales se formulará una pregunta",
"Question" : "Pregunta",
+ "What to ask about the images." : "Que preguntar sobre las imágenes.",
"Generated response" : "Respuesta generada",
"The answer to the question" : "La respuesta a la pregunta",
+ "Audio chat" : "Chat de audio",
"Voice chat with the assistant" : "Chat de voz con el asistente",
"System prompt" : "Prompt del sistema",
"Define rules and assumptions that the assistant should follow during the conversation." : "Definir las reglas y supuestos que el asistente debe seguir durante la conversación.",
"Chat voice message" : "Mensaje de voz del chat",
+ "Describe a task that you want the assistant to do or ask a question." : "Describa una tarea que desea que el asistente realice o haga una pregunta.",
"Chat history" : "Historial de la conversación",
+ "The history of chat messages before the current message, starting with a message by the user." : "El historial de mensajes de chat anterior al mensaje actual, comenzando con un mensaje de parte del usuario.",
"Input transcript" : "Transcripción de entrada",
"Transcription of the audio input" : "Transcripción de la entrada de audio",
"Response voice message" : "Mensaje de voz de respuesta",
@@ -347,6 +352,8 @@ OC.L10N.register(
"The audio to transcribe" : "El audio a transcribir",
"Transcription" : "Transcripción",
"The transcribed text" : "El texto transcrito",
+ "Chat by voice with an agent" : "Chatear a través de voz con un agente",
+ "Describe a task that you want the agent to do or ask a question." : "Describa una tarea que desea que el asistente realice o haga una pregunta.",
"Confirmation" : "Confirmación",
"Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Si se deben confirmar acciones solicitadas anteriormente: 0 para denegar y 1 para confirmar.",
"Conversation token" : "Token de conversación",
diff --git a/lib/l10n/es.json b/lib/l10n/es.json
index 29ee23631f9..fc43c0e1d91 100644
--- a/lib/l10n/es.json
+++ b/lib/l10n/es.json
@@ -273,6 +273,7 @@
"A valid Login must be provided" : "Se debe proporcionar un usuario válido",
"Login contains whitespace at the beginning or at the end" : "El usuario contiene espacios en blanco al inicio o al final",
"Login must not consist of dots only" : "El usuario no debe consistir sólo de puntos",
+ "Username is too long" : "El nombre de usuario es demasiado largo",
"Login is invalid because files already exist for this user" : "El nombre de inicio de sesión es inválido porque ya existen archivos para este usuario",
"Account disabled" : "Cuenta deshabilitada",
"Login canceled by app" : "Login cancelado por la app",
@@ -326,13 +327,17 @@
"Images" : "Imágenes",
"Images to ask a question about" : "Imágenes sobre las cuales se formulará una pregunta",
"Question" : "Pregunta",
+ "What to ask about the images." : "Que preguntar sobre las imágenes.",
"Generated response" : "Respuesta generada",
"The answer to the question" : "La respuesta a la pregunta",
+ "Audio chat" : "Chat de audio",
"Voice chat with the assistant" : "Chat de voz con el asistente",
"System prompt" : "Prompt del sistema",
"Define rules and assumptions that the assistant should follow during the conversation." : "Definir las reglas y supuestos que el asistente debe seguir durante la conversación.",
"Chat voice message" : "Mensaje de voz del chat",
+ "Describe a task that you want the assistant to do or ask a question." : "Describa una tarea que desea que el asistente realice o haga una pregunta.",
"Chat history" : "Historial de la conversación",
+ "The history of chat messages before the current message, starting with a message by the user." : "El historial de mensajes de chat anterior al mensaje actual, comenzando con un mensaje de parte del usuario.",
"Input transcript" : "Transcripción de entrada",
"Transcription of the audio input" : "Transcripción de la entrada de audio",
"Response voice message" : "Mensaje de voz de respuesta",
@@ -345,6 +350,8 @@
"The audio to transcribe" : "El audio a transcribir",
"Transcription" : "Transcripción",
"The transcribed text" : "El texto transcrito",
+ "Chat by voice with an agent" : "Chatear a través de voz con un agente",
+ "Describe a task that you want the agent to do or ask a question." : "Describa una tarea que desea que el asistente realice o haga una pregunta.",
"Confirmation" : "Confirmación",
"Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Si se deben confirmar acciones solicitadas anteriormente: 0 para denegar y 1 para confirmar.",
"Conversation token" : "Token de conversación",
diff --git a/lib/private/Accounts/AccountManager.php b/lib/private/Accounts/AccountManager.php
index 9c7c35d4a6b..d00b1d2e9a3 100644
--- a/lib/private/Accounts/AccountManager.php
+++ b/lib/private/Accounts/AccountManager.php
@@ -78,6 +78,7 @@ class AccountManager implements IAccountManager {
self::PROPERTY_PRONOUNS => self::SCOPE_FEDERATED,
self::PROPERTY_ROLE => self::SCOPE_LOCAL,
self::PROPERTY_TWITTER => self::SCOPE_LOCAL,
+ self::PROPERTY_BLUESKY => self::SCOPE_LOCAL,
self::PROPERTY_WEBSITE => self::SCOPE_LOCAL,
];
@@ -564,6 +565,13 @@ class AccountManager implements IAccountManager {
],
[
+ 'name' => self::PROPERTY_BLUESKY,
+ 'value' => '',
+ 'scope' => $scopes[self::PROPERTY_BLUESKY],
+ 'verified' => self::NOT_VERIFIED,
+ ],
+
+ [
'name' => self::PROPERTY_FEDIVERSE,
'value' => '',
'scope' => $scopes[self::PROPERTY_FEDIVERSE],
@@ -713,6 +721,47 @@ class AccountManager implements IAccountManager {
}
}
+ private function validateBlueSkyHandle(string $text): bool {
+ if ($text === '') {
+ return true;
+ }
+
+ $lowerText = strtolower($text);
+
+ if ($lowerText === 'bsky.social') {
+ // "bsky.social" itself is not a valid handle
+ return false;
+ }
+
+ if (str_ends_with($lowerText, '.bsky.social')) {
+ $parts = explode('.', $lowerText);
+
+ // Must be exactly: username.bsky.social → 3 parts
+ if (count($parts) !== 3 || $parts[1] !== 'bsky' || $parts[2] !== 'social') {
+ return false;
+ }
+
+ $username = $parts[0];
+
+ // Must be 3–18 chars, alphanumeric/hyphen, no start/end hyphen
+ return preg_match('/^[a-z0-9][a-z0-9-]{2,17}$/', $username) === 1;
+ }
+
+ // Allow custom domains (Bluesky handle via personal domain)
+ return filter_var($text, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) !== false;
+ }
+
+
+ private function sanitizePropertyBluesky(IAccountProperty $property): void {
+ if ($property->getName() === self::PROPERTY_BLUESKY) {
+ if (!$this->validateBlueSkyHandle($property->getValue())) {
+ throw new InvalidArgumentException(self::PROPERTY_BLUESKY);
+ }
+
+ $property->setValue($property->getValue());
+ }
+ }
+
/**
* @throws InvalidArgumentException If the property value is not a valid fediverse handle (username@instance where instance is a valid domain)
*/
@@ -805,6 +854,15 @@ class AccountManager implements IAccountManager {
}
try {
+ $property = $account->getProperty(self::PROPERTY_BLUESKY);
+ if ($property->getValue() !== '') {
+ $this->sanitizePropertyBluesky($property);
+ }
+ } catch (PropertyDoesNotExistException $e) {
+ // valid case, nothing to do
+ }
+
+ try {
$property = $account->getProperty(self::PROPERTY_FEDIVERSE);
if ($property->getValue() !== '') {
$this->sanitizePropertyFediverse($property);
diff --git a/lib/private/AppFramework/App.php b/lib/private/AppFramework/App.php
index 77135986d5f..7bf32852209 100644
--- a/lib/private/AppFramework/App.php
+++ b/lib/private/AppFramework/App.php
@@ -71,7 +71,6 @@ class App {
return null;
}
-
/**
* Shortcut for calling a controller method and printing the result
*
@@ -82,7 +81,12 @@ class App {
* @param array $urlParams list of URL parameters (optional)
* @throws HintException
*/
- public static function main(string $controllerName, string $methodName, DIContainer $container, ?array $urlParams = null) {
+ public static function main(
+ string $controllerName,
+ string $methodName,
+ DIContainer $container,
+ ?array $urlParams = null,
+ ): void {
/** @var IProfiler $profiler */
$profiler = $container->get(IProfiler::class);
$eventLogger = $container->get(IEventLogger::class);
@@ -134,8 +138,7 @@ class App {
$eventLogger->start('app:controller:dispatcher', 'Initialize dispatcher and pre-middleware');
// initialize the dispatcher and run all the middleware before the controller
- /** @var Dispatcher $dispatcher */
- $dispatcher = $container['Dispatcher'];
+ $dispatcher = $container->get(Dispatcher::class);
$eventLogger->end('app:controller:dispatcher');
@@ -211,25 +214,4 @@ class App {
}
}
}
-
- /**
- * Shortcut for calling a controller method and printing the result.
- * Similar to App:main except that no headers will be sent.
- *
- * @param string $controllerName the name of the controller under which it is
- * stored in the DI container
- * @param string $methodName the method that you want to call
- * @param array $urlParams an array with variables extracted from the routes
- * @param DIContainer $container an instance of a pimple container.
- */
- public static function part(string $controllerName, string $methodName, array $urlParams,
- DIContainer $container) {
- $container['urlParams'] = $urlParams;
- $controller = $container[$controllerName];
-
- $dispatcher = $container['Dispatcher'];
-
- [, , $output] = $dispatcher->dispatch($controller, $methodName);
- return $output;
- }
}
diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php
index 5ccc1b7d348..0bce8ac193b 100644
--- a/lib/private/AppFramework/DependencyInjection/DIContainer.php
+++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php
@@ -63,7 +63,7 @@ use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
class DIContainer extends SimpleContainer implements IAppContainer {
- private string $appName;
+ protected string $appName;
private array $middleWares = [];
private ServerContainer $server;
@@ -152,7 +152,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$this->registerDeprecatedAlias('Dispatcher', Dispatcher::class);
$this->registerService(Dispatcher::class, function (ContainerInterface $c) {
return new Dispatcher(
- $c->get('Protocol'),
+ $c->get(Http::class),
$c->get(MiddlewareDispatcher::class),
$c->get(IControllerMethodReflector::class),
$c->get(IRequest::class),
diff --git a/lib/private/AppFramework/Utility/SimpleContainer.php b/lib/private/AppFramework/Utility/SimpleContainer.php
index ed26e75ec89..0db3bfc1c77 100644
--- a/lib/private/AppFramework/Utility/SimpleContainer.php
+++ b/lib/private/AppFramework/Utility/SimpleContainer.php
@@ -196,7 +196,9 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer {
$this->registerService($alias, function (ContainerInterface $container) use ($target, $alias): mixed {
try {
$logger = $container->get(LoggerInterface::class);
- $logger->debug('The requested alias "' . $alias . '" is deprecated. Please request "' . $target . '" directly. This alias will be removed in a future Nextcloud version.', ['app' => 'serverDI']);
+ $logger->debug('The requested alias "' . $alias . '" is deprecated. Please request "' . $target . '" directly. This alias will be removed in a future Nextcloud version.', [
+ 'app' => $this->appName ?? 'serverDI',
+ ]);
} catch (ContainerExceptionInterface $e) {
// Could not get logger. Continue
}
diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php
index 88bdc377e2b..f86cbc341a4 100644
--- a/lib/private/DB/Connection.php
+++ b/lib/private/DB/Connection.php
@@ -16,6 +16,7 @@ use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Exception\ConnectionLost;
+use Doctrine\DBAL\Platforms\MariaDBPlatform;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
@@ -915,11 +916,13 @@ class Connection extends PrimaryReadReplicaConnection {
}
/**
- * @return IDBConnection::PLATFORM_MYSQL|IDBConnection::PLATFORM_ORACLE|IDBConnection::PLATFORM_POSTGRES|IDBConnection::PLATFORM_SQLITE
+ * @return IDBConnection::PLATFORM_MYSQL|IDBConnection::PLATFORM_ORACLE|IDBConnection::PLATFORM_POSTGRES|IDBConnection::PLATFORM_SQLITE|IDBConnection::PLATFORM_MARIADB
*/
- public function getDatabaseProvider(): string {
+ public function getDatabaseProvider(bool $strict = false): string {
$platform = $this->getDatabasePlatform();
- if ($platform instanceof MySQLPlatform) {
+ if ($strict && $platform instanceof MariaDBPlatform) {
+ return IDBConnection::PLATFORM_MARIADB;
+ } elseif ($platform instanceof MySQLPlatform) {
return IDBConnection::PLATFORM_MYSQL;
} elseif ($platform instanceof OraclePlatform) {
return IDBConnection::PLATFORM_ORACLE;
diff --git a/lib/private/DB/ConnectionAdapter.php b/lib/private/DB/ConnectionAdapter.php
index 78ca780f218..d9ccb3c54f2 100644
--- a/lib/private/DB/ConnectionAdapter.php
+++ b/lib/private/DB/ConnectionAdapter.php
@@ -237,10 +237,10 @@ class ConnectionAdapter implements IDBConnection {
}
/**
- * @return self::PLATFORM_MYSQL|self::PLATFORM_ORACLE|self::PLATFORM_POSTGRES|self::PLATFORM_SQLITE
+ * @return self::PLATFORM_MYSQL|self::PLATFORM_ORACLE|self::PLATFORM_POSTGRES|self::PLATFORM_SQLITE|self::PLATFORM_MARIADB
*/
- public function getDatabaseProvider(): string {
- return $this->inner->getDatabaseProvider();
+ public function getDatabaseProvider(bool $strict = false): string {
+ return $this->inner->getDatabaseProvider($strict);
}
/**
diff --git a/lib/private/DB/QueryBuilder/QueryBuilder.php b/lib/private/DB/QueryBuilder/QueryBuilder.php
index 1d1ccd29bf7..1d44c049793 100644
--- a/lib/private/DB/QueryBuilder/QueryBuilder.php
+++ b/lib/private/DB/QueryBuilder/QueryBuilder.php
@@ -96,6 +96,7 @@ class QueryBuilder implements IQueryBuilder {
return match($this->connection->getDatabaseProvider()) {
IDBConnection::PLATFORM_ORACLE => new OCIExpressionBuilder($this->connection, $this, $this->logger),
IDBConnection::PLATFORM_POSTGRES => new PgSqlExpressionBuilder($this->connection, $this, $this->logger),
+ IDBConnection::PLATFORM_MARIADB,
IDBConnection::PLATFORM_MYSQL => new MySqlExpressionBuilder($this->connection, $this, $this->logger),
IDBConnection::PLATFORM_SQLITE => new SqliteExpressionBuilder($this->connection, $this, $this->logger),
};
@@ -121,6 +122,7 @@ class QueryBuilder implements IQueryBuilder {
return match($this->connection->getDatabaseProvider()) {
IDBConnection::PLATFORM_ORACLE => new OCIFunctionBuilder($this->connection, $this, $this->helper),
IDBConnection::PLATFORM_POSTGRES => new PgSqlFunctionBuilder($this->connection, $this, $this->helper),
+ IDBConnection::PLATFORM_MARIADB,
IDBConnection::PLATFORM_MYSQL => new FunctionBuilder($this->connection, $this, $this->helper),
IDBConnection::PLATFORM_SQLITE => new SqliteFunctionBuilder($this->connection, $this, $this->helper),
};
diff --git a/lib/private/Profile/Actions/BlueskyAction.php b/lib/private/Profile/Actions/BlueskyAction.php
new file mode 100644
index 00000000000..d05682aac1a
--- /dev/null
+++ b/lib/private/Profile/Actions/BlueskyAction.php
@@ -0,0 +1,65 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OC\Profile\Actions;
+
+use OCP\Accounts\IAccountManager;
+use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\L10N\IFactory;
+use OCP\Profile\ILinkAction;
+
+class BlueskyAction implements ILinkAction {
+ private string $value = '';
+
+ public function __construct(
+ private IAccountManager $accountManager,
+ private IFactory $l10nFactory,
+ private IURLGenerator $urlGenerator,
+ ) {
+ }
+
+ public function preload(IUser $targetUser): void {
+ $account = $this->accountManager->getAccount($targetUser);
+ $this->value = $account->getProperty(IAccountManager::PROPERTY_BLUESKY)->getValue();
+ }
+
+ public function getAppId(): string {
+ return 'core';
+ }
+
+ public function getId(): string {
+ return IAccountManager::PROPERTY_BLUESKY;
+ }
+
+ public function getDisplayId(): string {
+ return $this->l10nFactory->get('lib')->t('Bluesky');
+ }
+
+ public function getTitle(): string {
+ $displayUsername = $this->value;
+ return $this->l10nFactory->get('lib')->t('View %s on Bluesky', [$displayUsername]);
+ }
+
+ public function getPriority(): int {
+ return 60;
+ }
+
+ public function getIcon(): string {
+ return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/bluesky.svg'));
+ }
+
+ public function getTarget(): ?string {
+ if (empty($this->value)) {
+ return null;
+ }
+ $username = $this->value;
+ return 'https://bsky.app/profile/' . $username;
+ }
+}
diff --git a/lib/private/Profile/ProfileManager.php b/lib/private/Profile/ProfileManager.php
index 1ade208fbcf..7c15ed614aa 100644
--- a/lib/private/Profile/ProfileManager.php
+++ b/lib/private/Profile/ProfileManager.php
@@ -14,6 +14,7 @@ use OC\Core\Db\ProfileConfig;
use OC\Core\Db\ProfileConfigMapper;
use OC\Core\ResponseDefinitions;
use OC\KnownUser\KnownUserService;
+use OC\Profile\Actions\BlueskyAction;
use OC\Profile\Actions\EmailAction;
use OC\Profile\Actions\FediverseAction;
use OC\Profile\Actions\PhoneAction;
@@ -56,6 +57,7 @@ class ProfileManager implements IProfileManager {
PhoneAction::class,
WebsiteAction::class,
TwitterAction::class,
+ BlueskyAction::class,
FediverseAction::class,
];
diff --git a/lib/public/Accounts/IAccountManager.php b/lib/public/Accounts/IAccountManager.php
index 92fc0002674..ae5535ef13b 100644
--- a/lib/public/Accounts/IAccountManager.php
+++ b/lib/public/Accounts/IAccountManager.php
@@ -97,10 +97,16 @@ interface IAccountManager {
/**
* @since 15.0.0
+ * @deprecated 32.0.0
*/
public const PROPERTY_TWITTER = 'twitter';
/**
+ * @since 32.0.0
+ */
+ public const PROPERTY_BLUESKY = 'bluesky';
+
+ /**
* @since 26.0.0
*/
public const PROPERTY_FEDIVERSE = 'fediverse';
@@ -160,6 +166,7 @@ interface IAccountManager {
self::PROPERTY_PRONOUNS,
self::PROPERTY_ROLE,
self::PROPERTY_TWITTER,
+ self::PROPERTY_BLUESKY,
self::PROPERTY_WEBSITE,
];
diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php
index e0fe603ec57..ea9b71d8958 100644
--- a/lib/public/IDBConnection.php
+++ b/lib/public/IDBConnection.php
@@ -45,6 +45,11 @@ interface IDBConnection {
public const PLATFORM_SQLITE = 'sqlite';
/**
+ * @since 32.0.0
+ */
+ public const PLATFORM_MARIADB = 'mariadb';
+
+ /**
* Gets the QueryBuilder for the connection.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder
@@ -357,11 +362,15 @@ interface IDBConnection {
/**
* Returns the database provider name
+ *
* @link https://github.com/nextcloud/server/issues/30877
+ *
+ * @param bool $strict differentiate between database flavors, e.g. MySQL vs MariaDB
+ * @return self::PLATFORM_MYSQL|self::PLATFORM_ORACLE|self::PLATFORM_POSTGRES|self::PLATFORM_SQLITE|self::PLATFORM_MARIADB
+ * @since 32.0.0 Optional parameter $strict was added
* @since 28.0.0
- * @return self::PLATFORM_MYSQL|self::PLATFORM_ORACLE|self::PLATFORM_POSTGRES|self::PLATFORM_SQLITE
*/
- public function getDatabaseProvider(): string;
+ public function getDatabaseProvider(bool $strict = false): string;
/**
* Get the shard definition by name, if configured
diff --git a/lib/public/Profile/IProfileManager.php b/lib/public/Profile/IProfileManager.php
index f4e90e39d12..aec06fb4c86 100644
--- a/lib/public/Profile/IProfileManager.php
+++ b/lib/public/Profile/IProfileManager.php
@@ -55,6 +55,7 @@ interface IProfileManager {
IAccountManager::PROPERTY_EMAIL => self::VISIBILITY_SHOW_USERS_ONLY,
IAccountManager::PROPERTY_PHONE => self::VISIBILITY_SHOW_USERS_ONLY,
IAccountManager::PROPERTY_TWITTER => self::VISIBILITY_SHOW,
+ IAccountManager::PROPERTY_BLUESKY => self::VISIBILITY_SHOW,
IAccountManager::PROPERTY_WEBSITE => self::VISIBILITY_SHOW,
IAccountManager::PROPERTY_PRONOUNS => self::VISIBILITY_SHOW,
];