Skip to content

Commit

Permalink
Wrapped up media API and clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
stevandoMoodle committed Feb 2, 2023
1 parent 0f81ccc commit 4562795
Show file tree
Hide file tree
Showing 11 changed files with 399 additions and 110 deletions.
12 changes: 6 additions & 6 deletions application/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions application/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
medias_directory: '%kernel.project_dir%/public/medias'

services:
# default configuration for services in *this* file
Expand Down
89 changes: 89 additions & 0 deletions application/src/Controller/BackOfficeController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace App\Controller;

use App\Entity\Passwords;
use App\Entity\Tokens;
use App\Entity\Users;
use App\Traits\GeneralTrait;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

/**
* @Route("/{serverID}/backoffice")
*/
class BackOfficeController extends AbstractController {

use GeneralTrait;

/**
* Create admin user.
*
* @Route("/create-admin", name="createAdmin")
* @param string $serverID
* @param Request $request
* @return JsonResponse
*/
public function createAdmin(string $serverID, Request $request) {
$method = $request->getMethod();
if ($method === 'POST') {
$entityManager = $this->getDoctrine()->getManager();

$user = $entityManager->getRepository(Users::class)->findOneBy(['userid' => '@admin:synapse']);
if (!$user) {
$user = new Users();
$user->setServerid($serverID);
$user->setUserid('@admin:synapse');
$user->setDisplayname('Admin User');
$user->setAdmin(true);
}

// Process tokens.
$token = $entityManager->getRepository(Tokens::class)
->findOneBy(['userid' => $user->getId()]);
if (!$token) {
// New user, or existing user without any associated Tokens.
$token = new Tokens();
$token->setAccesstoken($this->generateToken('access-token'));
$token->setExpiresinms();
$token->setServerid($serverID);

$user->addtoken($token);
$token->setUserid($user);
$entityManager->persist($token);
}

// Process password.
$passwords = $entityManager->getRepository(Passwords::class)
->findOneBy(['userid' => $user->getId()]);
if (!$passwords) {
// 1. Generates and returns token as password.
// 2. Generates and returns token pattern.
$password = $this->hashPassword('password', null, true);

// New user, or existing user without any associated Tokens.
$passwords = new Passwords();
$passwords->setPassword($password['token']);

$user->addPasswords($passwords);
$user->setPasswordpattern($password['pattern']);
$passwords->setUserid($user);
$entityManager->persist($passwords);
}
$entityManager->persist($user);
$entityManager->flush();

return new JsonResponse((object)[
'user_id' => $user->getUserid(),
'password' => 'password'
], 200);
} else {
return new JsonResponse(
'Only POST method is allowed.',
403
);
}
}
}
108 changes: 97 additions & 11 deletions application/src/Controller/MatrixController.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,24 @@ public function endpoint(): JsonResponse
* Login a user.
*
* @Route("/login", name="login")
* @param string $serverID
* @param Request $request
* @return JsonResponse
*/
public function login(Request $request): JsonResponse {
public function login(string $serverID, Request $request): JsonResponse {
$payload = json_decode($request->getContent());
$check = $this->validateRequest((array)$payload, ['identifier', 'type']);
if (!$check['status']) {
return $check['message'];
}

// 1. Check if type is in the $palyload->identifier.
// 2. Return loginidentifier property if no error.
$check = $this->loginIdentifierType($payload->identifier);
if (!$check['status']) {
return $check['message'];
}

if ($payload->type === 'm.login.password') {
if (!isset($payload->password)) {
return new JsonResponse((object) [
Expand All @@ -56,13 +64,6 @@ public function login(Request $request): JsonResponse {
], 400);
}

// 1. Check if type is in the $palyload->identifier.
// 2. Return loginidentifier property if no error.
$check = $this->loginIdentifierType($payload->identifier);
if (!$check['status']) {
return $check['message'];
}

$entityManager = $this->getDoctrine()->getManager();
$user = $entityManager->getRepository(Users::class)->findOneBy($check['loginidentifier']);
$password = $entityManager->getRepository(Passwords::class)->findOneBy([
Expand All @@ -74,6 +75,11 @@ public function login(Request $request): JsonResponse {
if ($user && $password) {
$token = $entityManager->getRepository(Tokens::class)->findOneBy(['userid' => $user->getId()]);

// Assign client server id if the server id is NULL.
if (is_null($token->getServerid())) {
$token->setServerid($serverID);
}

// Check if refresh_token is in the body and set to true,
// then generate a new refresh_token.
if (isset($payload->refresh_token) && $payload->refresh_token === true) {
Expand Down Expand Up @@ -102,6 +108,42 @@ public function login(Request $request): JsonResponse {
], 403);
}

/**
* Refresh the tokens.
*
* @Route("/refresh", name="refresh")
* @param string $serverID
* @param Request $request
* @return JsonResponse
*/
public function refresh(string $serverID, Request $request): JsonResponse {
$payload = json_decode($request->getContent());
$check = $this->validateRequest((array)$payload, ['refresh_token']);
if (!$check['status']) {
return $check['message'];
}

$tokens = $this->getToken($serverID, $payload->refresh_token);
if (!empty($tokens)) {
$tokens->setAccesstoken($this->generateToken('access-token'));
$tokens->setRefreshtoken($this->generateToken('refresh-token'));

$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($tokens);
$entityManager->flush();

return new JsonResponse((object)[
'access_token' => $tokens->getAccesstoken(),
'refresh_token' => $tokens->getRefreshtoken()
], 200);
} else {
return new JsonResponse((object)[
'errcode' => 'M_UNKNOWN_TOKEN',
'refresh_token' => 'Invalid token'
], 401);
}
}

/**
* Create Matrix room.
*
Expand Down Expand Up @@ -141,6 +183,44 @@ public function createRoom(string $serverID, Request $request): JsonResponse {
], 200);
}

/**
* Create Matrix room.
*
* @Route("/rooms/{roomID}/kick", name="kick")
* @param Request $request
* @return JsonResponse
*/
public function kick(string $roomID, Request $request) : JsonResponse {
// Check room exists.
$roomCheck = $this->roomExists($roomID);
if (!$roomCheck['status']) {
return $roomCheck['message'];
}

$payload = json_decode($request->getContent());
$check = $this->validateRequest((array)$payload, ['reason', 'user_id']);
if (!$check['status']) {
return $check['message'];
}

$roommembers = $this->getRoomMember($roomID, $payload->user_id);
if (empty($roommembers)) {
return new JsonResponse((object) [
'errcode' => 'M_NOT_MEMBER',
'error' => 'The target user_id is not a room member.'
], 403);
}

// Update th membership.
$roommembers->setState('leave');
$roommembers->setReason($payload->reason);

$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($roommembers);
$entityManager->flush();
return new JsonResponse((object)[]);
}

/**
* Update various room state components.
*
Expand All @@ -157,7 +237,7 @@ public function roomState(string $serverID, string $roomID, string $eventType, R
return $accessCheck['message'];
}

// 3. Check room exists. If exists, "room" property is added.
// Check room exists. If exists, "room" property is added.
$roomCheck = $this->roomExists($roomID, true);
if (!$roomCheck['status']) {
return $roomCheck['message'];
Expand Down Expand Up @@ -218,10 +298,16 @@ public function inviteUser(string $roomID, Request $request): JsonResponse {
$userID = $payload->userid;

// Check if the user has already been invited.
$this->isUserInvited($roomID, $userID);
$check = $this->isUserInvited($roomID, $userID);
if (!$check['status']) {
return $check['message'];
}

// Check if the user is banned from the group.
$this->isUserBanned($roomID, $userID);
$check = $this->isUserBanned($roomID, $userID);
if (!$check['status']) {
return $check['message'];
}

// Check if "currentuserid" is sent with the body.
if (!isset($payload->currentuserid)) {
Expand Down
43 changes: 24 additions & 19 deletions application/src/Controller/MediaController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

namespace App\Controller;

use App\Entity\Medias;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use App\Service\ApiCheck;

use App\Traits\GeneralTrait;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\File;

/**
* API Controller to serve a mock of the Matrix API for media requests.
Expand All @@ -16,6 +19,8 @@
*/
class MediaController extends AbstractController {

use GeneralTrait;

/**
* @Route("", name="endpoint")
*/
Expand All @@ -36,30 +41,30 @@ public function endpoint(): JsonResponse
* @return JsonResponse
*/
public function uploadMedia(string $serverID, Request $request): JsonResponse {
// Check call auth.
$authCheck = ApiCheck::checkAuth($request);
if (!$authCheck['status']) {
// Auth check failed, return error info.
return $authCheck['message'];
// 1. Check call auth.
// 2. Check HTTP method is accepted.
$accessCheck = $this->authHttpCheck(['POST'], $request);
if (!$accessCheck['status']) {
return $accessCheck['message'];
}

// Check HTTP method is accepted.
$method = $request->getMethod();
$methodCheck = ApiCheck::checkMethod(['POST'], $method);
if (!$methodCheck['status']) {
// Method check failed, return error info.
return $methodCheck['message'];
}
$filename = $request->query->get('filename') ?? sha1(uniqid()) . '.jpg';
$filepath = $this->getParameter('medias_directory').'/'.$filename;
$contenturi = $request->getSchemeAndHttpHost() . "/medias/$filename";

$filesystem = new Filesystem();
$filesystem->dumpFile($filepath, file_get_contents("php://input"));

$filename = $request->query->get('filename');
$host = $request->getHost();
$medias = new Medias();
$medias->setContenturi($contenturi);
$medias->setServerid($serverID);

// We don't care about the payload and storing it.
// Just assume everything is fine and return a fake URI for it.
$contentURI = 'mxc://' . $host . '/' . substr(hash('sha256', ($serverID . $filename . $host)), 0, 24);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($medias);
$entityManager->flush();

return new JsonResponse((object) [
'content_uri' => $contentURI,
'encode' => $contenturi,
], 200);
}
}
Loading

0 comments on commit 4562795

Please sign in to comment.