2424use OCP \AppFramework \Http \Attribute \PublicPage ;
2525use OCP \AppFramework \Http \DataResponse ;
2626use OCP \IRequest ;
27-
27+ use Psr \ Log \ LoggerInterface ;
2828/**
2929 * @psalm-suppress UndefinedClass
3030 * @psalm-suppress UndefinedDocblockClass
3131 */
32- final class WhiteboardController extends ApiController {
32+ final class WhiteboardController extends ApiController
33+ {
3334 public function __construct (
3435 $ appName ,
3536 IRequest $ request ,
@@ -39,14 +40,16 @@ public function __construct(
3940 private WhiteboardContentService $ contentService ,
4041 private ExceptionService $ exceptionService ,
4142 private ConfigService $ configService ,
43+ private LoggerInterface $ logger ,
4244 ) {
4345 parent ::__construct ($ appName , $ request );
4446 }
4547
4648 #[NoAdminRequired]
4749 #[NoCSRFRequired]
4850 #[PublicPage]
49- public function show (int $ fileId ): DataResponse {
51+ public function show (int $ fileId ): DataResponse
52+ {
5053 try {
5154 $ jwt = $ this ->getJwtFromRequest ();
5255
@@ -67,7 +70,8 @@ public function show(int $fileId): DataResponse {
6770 #[NoAdminRequired]
6871 #[NoCSRFRequired]
6972 #[PublicPage]
70- public function update (int $ fileId , array $ data ): DataResponse {
73+ public function update (int $ fileId , array $ data ): DataResponse
74+ {
7175 try {
7276 $ this ->validateBackendSharedToken ($ fileId );
7377
@@ -85,29 +89,33 @@ public function update(int $fileId, array $data): DataResponse {
8589 }
8690 }
8791
88- private function getJwtFromRequest (): string {
92+ private function getJwtFromRequest (): string
93+ {
8994 $ authHeader = $ this ->request ->getHeader ('Authorization ' );
9095 if (sscanf ($ authHeader , 'Bearer %s ' , $ jwt ) !== 1 ) {
9196 throw new UnauthorizedException ();
9297 }
93- return (string )$ jwt ;
98+ return (string ) $ jwt ;
9499 }
95100
96- private function getUserIdFromRequest (): string {
101+ private function getUserIdFromRequest (): string
102+ {
97103 return $ this ->request ->getHeader ('X-Whiteboard-User ' );
98104 }
99105
100- private function validateBackendSharedToken (int $ fileId ): void {
106+ private function validateBackendSharedToken (int $ fileId ): void
107+ {
101108 $ backendSharedToken = $ this ->request ->getHeader ('X-Whiteboard-Auth ' );
102109 if (!$ backendSharedToken || !$ this ->verifySharedToken ($ backendSharedToken , $ fileId )) {
103110 throw new InvalidUserException ('Invalid backend shared token ' );
104111 }
105112 }
106113
107- private function verifySharedToken (string $ token , int $ fileId ): bool {
114+ private function verifySharedToken (string $ token , int $ fileId ): bool
115+ {
108116 [$ roomId , $ timestamp , $ signature ] = explode (': ' , $ token );
109117
110- if ($ roomId !== (string )$ fileId ) {
118+ if ($ roomId !== (string ) $ fileId ) {
111119 return false ;
112120 }
113121
@@ -117,4 +125,32 @@ private function verifySharedToken(string $token, int $fileId): bool {
117125
118126 return hash_equals ($ expectedSignature , $ signature );
119127 }
128+
129+
130+ /**
131+ * Sync whiteboard data
132+ */
133+ #[NoAdminRequired]
134+ #[NoCSRFRequired]
135+ #[PublicPage]
136+ public function sync (int $ fileId , array $ data ): DataResponse
137+ {
138+ try {
139+ $ jwt = $ this ->getJwtFromRequest ();
140+
141+ $ userId = $ this ->jwtService ->getUserIdFromJWT ($ jwt );
142+
143+ $ user = $ this ->getUserFromIdServiceFactory ->create ($ userId )->getUser ();
144+
145+ $ file = $ this ->getFileServiceFactory ->create ($ user , $ fileId )->getFile ();
146+
147+ $ this ->contentService ->updateContent ($ file , $ data );
148+
149+ return new DataResponse (['status ' => 'success ' , 'version ' => $ data ['version ' ]]);
150+ } catch (Exception $ e ) {
151+ $ this ->logger ->error ('Error syncing whiteboard data: ' . $ e ->getMessage ());
152+
153+ return $ this ->exceptionService ->handleException ($ e );
154+ }
155+ }
120156}
0 commit comments