Skip to content
Open
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
49 changes: 39 additions & 10 deletions lib/Controller/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Notification\IManager as INotificationManager;
use OCP\Profile\IProfileManager;
use OCP\Security\Bruteforce\IThrottler;
use Psr\Log\LoggerInterface;
use SensitiveParameter;
Expand All @@ -69,6 +71,8 @@ public function __construct(
private IThrottler $throttler,
protected Config $talkConfig,
protected IGroupManager $groupManager,
protected IUserManager $userManager,
protected IProfileManager $profileManager,
) {
parent::__construct($appName, $request);
}
Expand Down Expand Up @@ -122,28 +126,54 @@ public function duplicateSession(): Response {
return $this->pageHandler();
}

/**
* @param string $token
* @param string $callUser
* @return TemplateResponse|RedirectResponse
* @throws HintException
*/
#[NoCSRFRequired]
#[PublicPage]
#[BruteForceProtection(action: 'talkRoomToken')]
#[UseSession]
#[FrontpageRoute(verb: 'GET', url: '/')]
public function index(string $token = '', string $callUser = ''): Response {
if ($callUser !== '') {
$user = $this->userSession->getUser();
if (!$user instanceof IUser) {
return new RedirectResponse($this->url->linkToRoute('spreed.Page.meetUser', ['user' => $callUser]));
}
$token = '';
}
return $this->pageHandler($token, $callUser);
}

#[NoCSRFRequired]
#[PublicPage]
#[BruteForceProtection(action: 'callUser')]
#[FrontpageRoute(verb: 'GET', url: '/meet/{user}', root: '')]
public function meetUser(string $user): Response {
$loggedInUser = $this->userSession->getUser();
if ($loggedInUser instanceof IUser) {
$response = $this->api->createRoom(Room::TYPE_ONE_TO_ONE, $user);
if ($response->getStatus() === Http::STATUS_OK
|| $response->getStatus() === Http::STATUS_CREATED) {
$data = $response->getData();
return $this->redirectToConversation($data['token']);
}
return new RedirectResponse($this->url->linkToRoute('spreed.Page.index'));
}

$targetUser = $this->userManager->get($user);
if (!$targetUser instanceof IUser
|| $this->talkConfig->isNotAllowedToCreateConversations($targetUser)
|| !$this->profileManager->isProfileFieldVisible('talk', $targetUser, null)) {
$response = new TemplateResponse('core', '404', [], TemplateResponse::RENDER_AS_GUEST);
$response->throttle(['action' => 'callUser', 'callUser' => $user]);
return $response;
}

$this->initialState->provideInitialState('meet_target_user_id', $user);
$this->initialState->provideInitialState('meet_target_display_name', $targetUser->getDisplayName());

return new TemplateResponse($this->appName, 'meet', [], TemplateResponse::RENDER_AS_GUEST);
}

/**
* @param string $token
* @param string $callUser
* @param string $password
* @return TemplateResponse|RedirectResponse
* @throws HintException
*/
Expand Down Expand Up @@ -283,7 +313,6 @@ protected function pageHandler(
}

/**
* @param string $token
* @return TemplateResponse|NotFoundResponse
*/
#[NoCSRFRequired]
Expand Down
89 changes: 89 additions & 0 deletions lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use OCA\DAV\CalDAV\TimezoneService;
use OCA\Talk\Capabilities;
use OCA\Talk\Chat\ChatManager;
use OCA\Talk\Config;
use OCA\Talk\Events\AAttendeeRemovedEvent;
use OCA\Talk\Events\BeforeRoomsFetchEvent;
Expand Down Expand Up @@ -104,7 +105,11 @@
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\Profile\IProfileManager;
use OCP\Security\Bruteforce\IThrottler;
use OCP\Security\RateLimiting\ILimiter;
use OCP\Security\RateLimiting\IRateLimitExceededException;
use OCP\Server;
use OCP\User\Events\UserLiveStatusEvent;
use OCP\UserStatus\IManager as IUserStatusManager;
Expand Down Expand Up @@ -160,6 +165,10 @@ public function __construct(
protected IL10N $l,
protected ThreadService $threadService,
protected Forced $forcedParameters,
protected IProfileManager $profileManager,
protected ILimiter $limiter,
protected IFactory $l10nFactory,
protected ChatManager $chatManager,
) {
parent::__construct($appName, $request);
}
Expand Down Expand Up @@ -855,6 +864,86 @@ protected function createOneToOneRoom(string $targetUserId): DataResponse {
}
}

/**
* Create a meet room for a guest reaching out to a user via their public profile
*
* @param string $targetUserId ID of the user to contact
* @param string $message Initial chat message posted in the conversation
* @param string $displayName Guest display name
* @return DataResponse<Http::STATUS_CREATED, array{token: string}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_FORBIDDEN|Http::STATUS_TOO_MANY_REQUESTS, null, array{}>
*
* 201: Room created successfully
* 403: Not allowed to create conversations
* 404: User not found or profile not visible
* 429: Rate limit exceeded
*/
#[PublicPage]
#[BruteForceProtection(action: 'talkRoomToken')]
#[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/meet/{targetUserId}', requirements: [
'apiVersion' => '(v4)',
])]
public function createMeetRoom(string $targetUserId, string $message = '', string $displayName = ''): DataResponse {
try {
$this->limiter->registerAnonRequest(
'create-anonymous-conversation',
5,
60 * 60,
$this->request->getRemoteAddress(),
);
} catch (IRateLimitExceededException) {
return new DataResponse(null, Http::STATUS_TOO_MANY_REQUESTS);
}

$user = $this->userManager->get($targetUserId);
if (!$user instanceof IUser) {
$response = new DataResponse(null, Http::STATUS_NOT_FOUND);
$response->throttle(['action' => 'talkRoomToken']);
return $response;
}

if ($this->talkConfig->isNotAllowedToCreateConversations($user)) {
return new DataResponse(null, Http::STATUS_FORBIDDEN);
}

if (!$this->profileManager->isProfileFieldVisible('talk', $user, null)) {
$response = new DataResponse(null, Http::STATUS_NOT_FOUND);
$response->throttle(['action' => 'talkRoomToken']);
return $response;
}

$l = $this->l10nFactory->get('spreed', $this->l10nFactory->getUserLanguage($user));

$trimmedDisplayName = trim($displayName);
if ($trimmedDisplayName !== '') {
$roomName = $l->t('Contact request from %s', [$trimmedDisplayName]);
} else {
$roomName = $l->t('Contact request');
}

$room = $this->roomService->createConversation(
Room::TYPE_PUBLIC,
$roomName,
$user,
lobbyState: Webinary::LOBBY_NON_MODERATORS,
);

$message = trim($message);
if ($message !== '') {
$participant = $this->participantService->joinRoomAsNewGuest($this->roomService, $room, '', true, null, trim($displayName) ?: null);
$this->chatManager->sendMessage(
$room,
$participant,
Attendee::ACTOR_GUESTS,
$participant->getAttendee()->getActorId(),
$message,
$this->timeFactory->getDateTime(),
);
$this->participantService->leaveRoomAsSession($room, $participant);
}

return new DataResponse(['token' => $room->getToken()], Http::STATUS_CREATED);
}

/**
* Add a room to the favorites
*
Expand Down
23 changes: 15 additions & 8 deletions lib/Profile/TalkAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ public function getDisplayId(): string {
#[\Override]
public function getTitle(): string {
$visitingUser = $this->userSession->getUser();
if (!$visitingUser || $visitingUser === $this->targetUser) {
if ($visitingUser === $this->targetUser) {
return $this->l->t('Open Talk');
}

return $this->l->t('Talk to %s', [$this->targetUser->getDisplayName()]);
}

Expand All @@ -69,17 +70,23 @@ public function getIcon(): string {

#[\Override]
public function getTarget(): ?string {
$visitingUser = $this->userSession->getUser();
if (
!$visitingUser
|| $this->config->isDisabledForUser($this->targetUser)
|| $this->config->isDisabledForUser($visitingUser)
) {
if ($this->config->isDisabledForUser($this->targetUser)) {
return null;
}

$visitingUser = $this->userSession->getUser();
if ($visitingUser === $this->targetUser) {
return $this->urlGenerator->linkToRouteAbsolute('spreed.Page.index');
}
return $this->urlGenerator->linkToRouteAbsolute('spreed.Page.index') . '?callUser=' . $this->targetUser->getUID();

if ($visitingUser && $this->config->isDisabledForUser($visitingUser)) {
return null;
}

if (!$visitingUser && $this->config->isNotAllowedToCreateConversations($this->targetUser)) {
return null;
}

return $this->urlGenerator->linkToRouteAbsolute('spreed.Page.meetUser', ['user' => $this->targetUser->getUID()]);
}
}
Loading
Loading