diff --git a/.github/workflows/saas-update-backend.yml b/.github/workflows/saas-update-backend.yml index 14bd269ef9..d27291cf67 100644 --- a/.github/workflows/saas-update-backend.yml +++ b/.github/workflows/saas-update-backend.yml @@ -13,7 +13,7 @@ jobs: deploy-php: runs-on: ubuntu-20.04 steps: - - run: 'echo "DOCKERTAGVERSION=2021.Q1.434" >> $GITHUB_ENV' + - run: 'echo "DOCKERTAGVERSION=2021.Q2.481" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/develop') run: 'echo "DOCKERTAG=develop" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=${{ env.DOCKERTAGVERSION }}-develop" >> $GITHUB_ENV' @@ -34,7 +34,7 @@ jobs: deploy-node: runs-on: ubuntu-20.04 steps: - - run: 'echo "DOCKERTAGVERSION=2021.Q1.434" >> $GITHUB_ENV' + - run: 'echo "DOCKERTAGVERSION=2021.Q2.481" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/develop') run: 'echo "DOCKERTAG=develop" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=${{ env.DOCKERTAGVERSION }}-develop" >> $GITHUB_ENV' diff --git a/.github/workflows/saas-update-front.yml b/.github/workflows/saas-update-front.yml index ebf900d681..53511211e9 100644 --- a/.github/workflows/saas-update-front.yml +++ b/.github/workflows/saas-update-front.yml @@ -48,7 +48,7 @@ jobs: runs-on: ubuntu-20.04 if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' steps: - - run: 'echo "DOCKERTAGVERSION=2021.Q1.434" >> $GITHUB_ENV' + - run: 'echo "DOCKERTAGVERSION=2021.Q2.481" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/develop') run: 'echo "DOCKERTAG=develop" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=${{ env.DOCKERTAGVERSION }}-develop" >> $GITHUB_ENV' diff --git a/changelog.md b/changelog.md index dd612a6be5..47c6c88953 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,64 @@ +# Twake 2021.Q2.481 + +### Messages + +- Fix a bug making too many desktop notifications at the same time. +- Fix a bug when sending a message using the send button, message now disapear as expected. +- Fix the "hidden notification" button that can be stuck on top or bottom of the channel list. + +### Console + +- Now if you change your language on Console it will affect Twake accordingly. +- Better onboarding of new users: automatic channel selection, add collaborators button, invite collaborators from Twake using console management app and more. +- Polishing console migration script, previous Twake users will soon uses the Console. + +# Twake 2021.Q1.434 + +### Messages + +- Default channels now available 🌟 You can set a channel as default, new users invited in workspace will be automatically added to this channel. + +### General + +- Console onboarding update (soon open source!) +- Multiple bug fixes + +# Twake 2021.Q1.401 + +### General + +- First elements of Twake new design, welcome to blue #3840f7 +- Cmd+K / Ctrl+K now working on all channels types (direct and workspace channels) +- Multiple bug fixes + +# Twake 2021.Q1.385 + +### General + +- Twake is on OVH! OVH is a french infrastructure provider, it is a big step for us. Good bye Amazon 👋 +- Started migration to NodeJS from PHP (30%) for faster and lighter server, compatibility with MongoDB and more! +- Move to socket.io from socketcluster for more robust websockets. +- We are now compatible with the Twake Console. Twake account and group management will be soon fully replaced by the Console. +- Big performances upgrades, we fixed a lot of memory leaks in the last weeks. + +### Channels + +- Ability to join and leave channels. +- Channel activity messages. +- Access and rights for channel creation updated (now everyone can create channels). +- Favorite direct channels, now you can put your direct channels in favorites too. +- Channel groups are back! Yes, you can again create groups of channels to organize your workspace. +- Channel members list: see who is in a channel and manage members + +### Notifications + +- Now you only receive badge notification for threads you follow and when you are mentionned. +- Other messages in channel will update the channel text to bold. + +### Drive + +- Ability to preview coding files and markdown files + # Twake 2020.Q4.137 ### General diff --git a/twake/backend/core/src/BuiltInConnectors/Common/Services/MainConnectorService.php b/twake/backend/core/src/BuiltInConnectors/Common/Services/MainConnectorService.php index a9d4e99e39..b854ea0523 100755 --- a/twake/backend/core/src/BuiltInConnectors/Common/Services/MainConnectorService.php +++ b/twake/backend/core/src/BuiltInConnectors/Common/Services/MainConnectorService.php @@ -139,12 +139,21 @@ public function saveDocument($id, $content){ return false; } $document = new BuiltInConnectorsEntity($cred["api_id"], $id); - $document->setValue($content); - $this->doctrine->persist($document); + if($content === null){ + $this->doctrine->remove($document); + }else{ + $document->setValue($content); + $this->doctrine->persist($document); + } $this->doctrine->flush(); return true; } + /** Remove connector document from db */ + public function removeDocument($id){ + return $this->saveDocument($id, null); + } + /** Get connector document from db */ public function getDocument($id){ $cred = $this->getConnectorKeys(); diff --git a/twake/backend/core/src/Twake/Calendar/Controller/Calendar.php b/twake/backend/core/src/Twake/Calendar/Controller/Calendar.php index ac1217927e..0e1f969b0b 100755 --- a/twake/backend/core/src/Twake/Calendar/Controller/Calendar.php +++ b/twake/backend/core/src/Twake/Calendar/Controller/Calendar.php @@ -31,7 +31,7 @@ public function save(Request $request) }else{ if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "calendar:".($object["id"] ? "edit" : "create"), - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); } return new Response(Array("data" => Array("object" => $res))); @@ -46,7 +46,7 @@ public function getAction(Request $request) }else{ if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "calendar:open", - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); } diff --git a/twake/backend/core/src/Twake/Calendar/Controller/Event.php b/twake/backend/core/src/Twake/Calendar/Controller/Event.php index 269df60dfa..ab207fcc9f 100755 --- a/twake/backend/core/src/Twake/Calendar/Controller/Event.php +++ b/twake/backend/core/src/Twake/Calendar/Controller/Event.php @@ -20,7 +20,7 @@ public function remove(Request $request) } if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "calendar:event:remove", - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); return new Response(Array("data" => Array("object" => $res))); } @@ -38,7 +38,7 @@ public function save(Request $request) } if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "calendar:event:".($object["id"] ? "edit" : "create"), - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); } return new Response(Array("data" => Array("object" => $res))); diff --git a/twake/backend/core/src/Twake/Core/Controller/Version.php b/twake/backend/core/src/Twake/Core/Controller/Version.php index f708732f4c..9e6c739437 100755 --- a/twake/backend/core/src/Twake/Core/Controller/Version.php +++ b/twake/backend/core/src/Twake/Core/Controller/Version.php @@ -48,9 +48,9 @@ function getVersion(Request $request) "auth_mode" => array_keys($auth), "auth" => $auth, "version" => [ - "current" => /* @VERSION_DETAIL */ "2021.Q1.434", + "current" => /* @VERSION_DETAIL */ "2021.Q2.481", "minimal" => [ - "web" => /* @MIN_VERSION_WEB */ "2021.Q1.385", + "web" => /* @MIN_VERSION_WEB */ "2021.Q1.481", "mobile" => /* @MIN_VERSION_MOBILE */ "2021.Q1.385", ] ], diff --git a/twake/backend/core/src/Twake/Discussion/Controller/Discussion.php b/twake/backend/core/src/Twake/Discussion/Controller/Discussion.php index ec75b93323..bb0bd16a2e 100755 --- a/twake/backend/core/src/Twake/Discussion/Controller/Discussion.php +++ b/twake/backend/core/src/Twake/Discussion/Controller/Discussion.php @@ -39,7 +39,7 @@ public function save(Request $request) $this->get("administration.counter")->incrementCounter("total_messages", 1); if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "message:send", - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); } } diff --git a/twake/backend/core/src/Twake/Discussion/Services/MessageSystem.php b/twake/backend/core/src/Twake/Discussion/Services/MessageSystem.php index 4e65786b5e..ed90e20599 100755 --- a/twake/backend/core/src/Twake/Discussion/Services/MessageSystem.php +++ b/twake/backend/core/src/Twake/Discussion/Services/MessageSystem.php @@ -580,6 +580,7 @@ public function sendToNode($channel, $message, $did_create){ $title = ""; $text = $this->buildShortText($message); + $body = $text; // we need original body just in case text gets updated further on if ($channel->getData()["is_direct"]) { $title = $senderName . " in " . $channel->getData()["company_name"]; }else{ @@ -622,8 +623,10 @@ public function sendToNode($channel, $message, $did_create){ "channel_id" => $messageArray["channel_id"], "date" => $messageArray["creation_date"] * 1000, "sender" => $messageArray["sender"], - "title" => $title, - "text" => $text + "sender_name" => $senderName, // username, because it's not convenient to make request to find out username by id + "title" => $title, + "text" => $text, + "body" => $body // original body of the message without sender ]; if($messageArray["message_type"] != 2){ //Ignore system messages diff --git a/twake/backend/core/src/Twake/Drive/Controller/Download.php b/twake/backend/core/src/Twake/Drive/Controller/Download.php index 62ae59db95..53e73b3e28 100755 --- a/twake/backend/core/src/Twake/Drive/Controller/Download.php +++ b/twake/backend/core/src/Twake/Drive/Controller/Download.php @@ -39,7 +39,7 @@ public function downloadfile(Request $request) if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "drive:download", - "userId" => $this->isConnected() ? $this->getUser()->getId() : "anonymous" + "userId" => $this->isConnected() ? ($this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId()) : "anonymous" ]); @$response = $this->get('driveupload.download')->download($workspace_id, $files_ids, $download, $versionId); diff --git a/twake/backend/core/src/Twake/Drive/Controller/DriveFile.php b/twake/backend/core/src/Twake/Drive/Controller/DriveFile.php index cefdd57078..cfcba1903d 100755 --- a/twake/backend/core/src/Twake/Drive/Controller/DriveFile.php +++ b/twake/backend/core/src/Twake/Drive/Controller/DriveFile.php @@ -48,7 +48,7 @@ public function save(Request $request) if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "drive:".($object["is_directory"] ? "directory" : "file") . ":" . ($object["id"] ? "edit" : "create"), - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); if (!empty($object["_once_set_access"]) && !empty($object["id"])) { diff --git a/twake/backend/core/src/Twake/Drive/Controller/Upload.php b/twake/backend/core/src/Twake/Drive/Controller/Upload.php index cd0d3dd78e..15c3028956 100755 --- a/twake/backend/core/src/Twake/Drive/Controller/Upload.php +++ b/twake/backend/core/src/Twake/Drive/Controller/Upload.php @@ -17,7 +17,7 @@ public function Preprocess(Request $request) if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "drive:file:create", - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); return new Response(Array("identifier" => $identifier)); @@ -41,7 +41,7 @@ public function Preview(Request $request) if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "drive:preview", - "userId" => $this->isConnected() ? $this->getUser()->getId() : "anonymous" + "userId" => $this->isConnected() ? ($this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId()) : "anonymous" ]); $this->get('driveupload.previewmanager')->generatePreviewFromFolder($request); diff --git a/twake/backend/core/src/Twake/Tasks/Controller/Board.php b/twake/backend/core/src/Twake/Tasks/Controller/Board.php index 30dffe5c87..58fe102711 100755 --- a/twake/backend/core/src/Twake/Tasks/Controller/Board.php +++ b/twake/backend/core/src/Twake/Tasks/Controller/Board.php @@ -20,7 +20,7 @@ public function remove(Request $request) } if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "tasks:board:remove", - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); return new Response(Array("data" => Array("object" => $res))); } @@ -35,7 +35,7 @@ public function save(Request $request) } if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "tasks:board:".($object["id"] ? "edit" : "create"), - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); return new Response(Array("data" => Array("object" => $res))); } diff --git a/twake/backend/core/src/Twake/Tasks/Controller/Task.php b/twake/backend/core/src/Twake/Tasks/Controller/Task.php index cb14484bd0..fa5f505fa5 100755 --- a/twake/backend/core/src/Twake/Tasks/Controller/Task.php +++ b/twake/backend/core/src/Twake/Tasks/Controller/Task.php @@ -20,7 +20,7 @@ public function remove(Request $request) }else{ if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "tasks:task:remove", - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); } return new Response(Array("data" => Array("object" => $res))); @@ -37,7 +37,7 @@ public function save(Request $request) } if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "tasks:task:".($object["id"] ? "edit" : "create"), - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); if (!$res) { @@ -55,7 +55,7 @@ public function getAction(Request $request) }else{ if($GLOBALS["segment_enabled"]) \Segment::track([ "event" => "tasks:task:get", - "userId" => $this->getUser()->getId() + "userId" => $this->getuser()->getIdentityProviderId() ?: $this->getUser()->getId() ]); } return new Response(Array("data" => $objects)); diff --git a/twake/backend/core/src/Twake/Users/Controller/Adapters/Console.php b/twake/backend/core/src/Twake/Users/Controller/Adapters/Console.php index bc5e10782f..1094cbbb43 100755 --- a/twake/backend/core/src/Twake/Users/Controller/Adapters/Console.php +++ b/twake/backend/core/src/Twake/Users/Controller/Adapters/Console.php @@ -34,10 +34,10 @@ function logoutSuccess(Request $request) try{ $message = json_decode(urldecode($request->query->get("error_code"))); }catch(\Exception $err){ - $message = "success"; + $message = false; } - return $this->redirect(rtrim($this->getParameter("env.frontend_server_name", $this->getParameter("env.server_name")), "/") . "/login" . "?error_code=".str_replace('+', '%20', urlencode(json_encode($message)))); + return $this->redirect(rtrim($this->getParameter("env.frontend_server_name", $this->getParameter("env.server_name")), "/") . "/login" . ($message ? ("?error_code=".str_replace('+', '%20', urlencode(json_encode($message)))) : "?auto")); } function logout(Request $request, $message = null) diff --git a/twake/backend/core/src/Twake/Users/Controller/Adapters/Console/ApplyUpdates.php b/twake/backend/core/src/Twake/Users/Controller/Adapters/Console/ApplyUpdates.php index 98fad748fb..9b36b7b274 100755 --- a/twake/backend/core/src/Twake/Users/Controller/Adapters/Console/ApplyUpdates.php +++ b/twake/backend/core/src/Twake/Users/Controller/Adapters/Console/ApplyUpdates.php @@ -17,10 +17,14 @@ class ApplyUpdates /** @var App */ protected $app = null; + /** @var String */ + protected $endpoint = null; + public function __construct(App $app) { $this->app = $app; $this->em = $app->getServices()->get("app.twake_doctrine"); + $this->endpoint = $app->getContainer()->getParameter("defaults.auth.console.provider"); $this->string_cleaner = $app->getServices()->get("app.string_cleaner"); $this->user_service = $app->getServices()->get("app.user"); } @@ -55,6 +59,13 @@ function updateCompany($companyDTO){ $company->setIdentityProvider("console"); $company->setIdentityProviderId($companyConsoleCode); + $avatar = $userDTO["company"]["details"]["avatar"]; + $picture = $companyDTO["value"] ?: ""; + if($avatar["type"] && $avatar["type"] !== "url"){ + $picture = rtrim($this->endpoint, "/") . "/avatars/" . $avatar["value"]; + } + $company->setLogo($picture); + // Format is {name: "string", limits: {}} $company->setPlan($companyDTO["company"]["plan"]); @@ -71,8 +82,6 @@ function updateCompany($companyDTO){ $this->app->getServices()->get("app.groups")->init($company); - //TODO: realtime update - return $company; } @@ -163,34 +172,26 @@ function updateUser($userDTO){ // Update user names $user->setEmail($email); $user->setPhone(""); - $user->setFirstName($userDTO["firstName"] ?: ($userDTO["fullName"] ?: "")); + $user->setFirstName($userDTO["firstName"] ?: ($userDTO["name"] ?: "")); $user->setLastName($userDTO["lastName"] ?: ""); $user->setMailVerified(!!$userDTO["isVerified"]); + $user->setIdentityProvider("console"); + $user->setIdentityProviderId($userConsoleId); - $user->setLanguage(@$userDTO["preferences"]["locale"] ?: "en"); - $user->setTimezone(@$userDTO["preferences"]["timezone"] ?: ""); + $user->setLanguage(@$userDTO["preference"]["locale"] ?: "en"); + $user->setTimezone(@$userDTO["preference"]["timeZone"] ?: ""); // Update user picture - $picture = $userDTO["picture"]; - if (($picture && (!$user->getThumbnail() || $user->getThumbnail()->getPublicLink() != $picture)) || ($user->getThumbnail() && !$picture)) { - if ($user->getThumbnail()) { - $this->em->remove($user->getThumbnail()); - } - if($picture){ - $thumbnail = new File(); - $thumbnail->setPublicLink($picture); - $user->setThumbnail($thumbnail); - $this->em->persist($thumbnail); - }else{ - $user->setThumbnail(null); - } + $avatar = $userDTO["avatar"]; + $picture = $avatar["value"] ?: ""; + if($avatar["type"] && $avatar["type"] !== "url"){ + $picture = rtrim($this->endpoint, "/") . "/avatars/" . $avatar["value"]; } + $user->setPicture($picture); $this->em->persist($user); $this->em->flush(); - //TODO websocket update - foreach($roles as $role){ $companyConsoleCode = $role["targetCode"]; $level = $role["roleCode"]; diff --git a/twake/backend/core/src/Twake/Users/Controller/UsersConnections.php b/twake/backend/core/src/Twake/Users/Controller/UsersConnections.php index d7c463c774..7be29712cb 100755 --- a/twake/backend/core/src/Twake/Users/Controller/UsersConnections.php +++ b/twake/backend/core/src/Twake/Users/Controller/UsersConnections.php @@ -49,7 +49,7 @@ public function login(Request $request) $response = new Response(); $logged = $this->getUser() && !is_string($this->getUser()); - if(!$logged){ + if(!$logged || ($usernameOrMail && $password)){ $loginResult = $this->get("app.user")->login($usernameOrMail, $password, $rememberMe, $request, $response); } diff --git a/twake/backend/core/src/Twake/Users/Entity/User.php b/twake/backend/core/src/Twake/Users/Entity/User.php index e7cfc9c0b9..186d6b1968 100755 --- a/twake/backend/core/src/Twake/Users/Entity/User.php +++ b/twake/backend/core/src/Twake/Users/Entity/User.php @@ -56,7 +56,12 @@ class User extends SearchableObject /** * @ORM\ManyToOne(targetEntity="Twake\Upload\Entity\File") */ - protected $thumbnail; + protected $thumbnail; //Old format depreciated (now with console) + + /** + * @ORM\Column(name="picture", type="twake_text") + */ + protected $picture; /** * @ORM\Column(name="workspaces", type="twake_text") @@ -344,6 +349,25 @@ public function setThumbnail($thumbnail) $this->thumbnail = $thumbnail; } + /** + * @return mixed + */ + public function getPicture() + { + if(!$this->picture){ + $this->setPicture($this->getThumbnail() ? $this->getThumbnail()->getPublicURL(2) : ""); + } + return $this->picture ?: ""; + } + + /** + * @param mixed $logo + */ + public function setPicture($picture) + { + $this->picture = $picture; + } + public function isActive() { $this->lastactivity = date("U"); @@ -534,7 +558,7 @@ public function getAsArray() "username" => $this->getUsername(), "firstname" => $this->getFirstName(), "lastname" => $this->getLastName(), - "thumbnail" => (($this->getThumbnail() == null) ? null : $this->getThumbnail()->getPublicURL(2)) . "", + "thumbnail" => $this->getPicture(), "identity_provider" => $this->getIdentityProvider(), "connected" => $this->isConnected(), "language" => $this->getLanguage(), @@ -558,12 +582,12 @@ public function getAsArray() $return["email"] = $return["email"]; $return["is_verified"] = $this->getMailVerified(); - $return["picture"] = $return["thumbnail"]; + $return["picture"] = $this->getPicture(); $return["first_name"] = $return["firstname"]; $return["last_name"] = $return["lastname"]; $return["created_at"] = ($this->getCreationDate() ? ($this->getCreationDate()->format('U') * 1000) : null); - $return["preferences"] = [ + $return["preference"] = [ "locale" => $this->getLanguage(), "timezone" => $this->timezone, ]; diff --git a/twake/backend/core/src/Twake/Users/Services/User.php b/twake/backend/core/src/Twake/Users/Services/User.php index baa4cfc426..39825b65dd 100755 --- a/twake/backend/core/src/Twake/Users/Services/User.php +++ b/twake/backend/core/src/Twake/Users/Services/User.php @@ -176,9 +176,11 @@ public function loginFromServiceWithToken($service_id, $external_id, $email, $us $thumbnail = new File(); $thumbnail->setPublicLink($picture); $user->setThumbnail($thumbnail); + $user->setPicture($thumbnail->getPublicURL(2)); $this->em->persist($thumbnail); }else{ $user->setThumbnail(null); + $user->setPicture(""); } } @@ -1023,6 +1025,7 @@ public function updateUserBasicData($userId, $firstName, $lastName, $thumbnail = $user->setLastName($lastName); if ($thumbnail == 'false' || $thumbnail == 'null') { $user->setThumbnail(null); + $user->setPicture(""); } else if ($thumbnail != null && !is_string($thumbnail)) { if ($user->getThumbnail()) { if ($uploader) { @@ -1033,6 +1036,7 @@ public function updateUserBasicData($userId, $firstName, $lastName, $thumbnail = $this->em->remove($user->getThumbnail()); } $user->setThumbnail($thumbnail); + $user->setPicture($thumbnail->getPublicURL(2)); } $this->em->persist($user); $this->em->flush(); diff --git a/twake/backend/core/src/Twake/Users/Services/Users.php b/twake/backend/core/src/Twake/Users/Services/Users.php index 570bbc8172..0259b944db 100755 --- a/twake/backend/core/src/Twake/Users/Services/Users.php +++ b/twake/backend/core/src/Twake/Users/Services/Users.php @@ -33,7 +33,8 @@ public function searchWithDB($options = Array(), $entity = false) $name = $options["name"]; $scope = $options["scope"] ?: "all"; - + if($scope !== "group" || $scope !== "workspace") $scope = "group"; + $usersArray = []; $usersEntities = []; @@ -72,10 +73,21 @@ public function searchWithDB($options = Array(), $entity = false) foreach($users as $user){ if($user){ - //TODO execute search filter - - $usersArray[] = [$user->getAsArray(), 0]; - $usersEntities[] = [$user, 0]; + $match = false; + foreach($user->getAsArray() as $key => $value){ + if(in_array($key, ["username", "firstname", "lastname", "email"])){ + foreach(explode(" ", $name) as $word){ + if(strpos(strtolower($value), strtolower($word)) !== false){ + $match = true; + } + } + } + } + + if($match){ + $usersArray[] = [$user->getAsArray(), 0]; + $usersEntities[] = [$user, 0]; + } } } @@ -95,6 +107,7 @@ public function searchWithES($options = Array(), $entity = false) $name = $options["name"]; $scope = $options["scope"] ?: "all"; + if($scope !== "group" || $scope !== "workspace") $scope = "group"; $workspace_id = $options["workspace_id"]; $group_id = $options["group_id"]; diff --git a/twake/backend/core/src/Twake/Workspaces/Entity/Group.php b/twake/backend/core/src/Twake/Workspaces/Entity/Group.php index 3fc62c3d83..386b475287 100755 --- a/twake/backend/core/src/Twake/Workspaces/Entity/Group.php +++ b/twake/backend/core/src/Twake/Workspaces/Entity/Group.php @@ -238,7 +238,7 @@ public function getLogoFile() public function getLogo() { if(!$this->logo){ - return $this->getLogoFile() ? $this->getLogoFile()->getPublicURL(2) : ""; + $this->setLogo($this->getLogoFile() ? $this->getLogoFile()->getPublicURL(2) : ""); } return $this->logo ?: ""; } @@ -399,6 +399,8 @@ public function getAsArray() "logo" => $this->getLogo(), "plan" => $this->getPlan(), "stats" => $this->getStats(), + "identity_provider" => $this->getIdentityProvider(), + "identity_provider_id" => $this->getIdentityProviderId(), ); } diff --git a/twake/backend/core/src/Twake/Workspaces/Entity/Workspace.php b/twake/backend/core/src/Twake/Workspaces/Entity/Workspace.php index 1c82ed3da2..9882cfb381 100755 --- a/twake/backend/core/src/Twake/Workspaces/Entity/Workspace.php +++ b/twake/backend/core/src/Twake/Workspaces/Entity/Workspace.php @@ -10,7 +10,7 @@ /** * Workspace * - * @ORM\Table(name="workspace",options={"engine":"MyISAM", "scylladb_keys": {{"id":"ASC"}, {"group_id":"ASC", "id":"ASC"}}}) + * @ORM\Table(name="workspace",options={"engine":"MyISAM", "scylladb_keys": {{"id":"ASC"}, {"group_id":"ASC", "id":"ASC"}, {"group_id":"ASC"}}}) * @ORM\Entity() */ class Workspace extends SearchableObject @@ -206,7 +206,7 @@ public function getLogoFile() public function getLogo() { if(!$this->logo){ - return $this->getLogoFile() ? $this->getLogoFile()->getPublicURL(2) : ""; + $this->setLogo($this->getLogoFile() ? $this->getLogoFile()->getPublicURL(2) : ""); } return $this->logo ?: ""; } diff --git a/twake/backend/core/src/Twake/Workspaces/Services/WorkspaceMembers.php b/twake/backend/core/src/Twake/Workspaces/Services/WorkspaceMembers.php index f9f69405e7..148aa9077b 100755 --- a/twake/backend/core/src/Twake/Workspaces/Services/WorkspaceMembers.php +++ b/twake/backend/core/src/Twake/Workspaces/Services/WorkspaceMembers.php @@ -318,21 +318,6 @@ public function addMemberByMail($workspaceId, $mail, $asExterne, $currentUserId $this->doctrine->flush(); $retour = "mail"; } - - if($sendEmail){ - - //Send mail - $this->twake_mailer->send($mail, "inviteToWorkspaceMail", Array( - "_language" => $currentUser ? $currentUser->getLanguage() : "en", - "mail" => $mail, - "sender_user" => $currentUser ? $currentUser->getUsername() : "TwakeBot", - "sender_user_mail" => $currentUser ? $currentUser->getEmail() : "noreply@twakeapp.com", - "workspace" => $workspace->getName(), - "group" => $workspace->getGroup()->getDisplayName() - )); - - } - return $retour; } diff --git a/twake/backend/core/src/Twake/Workspaces/Services/Workspaces.php b/twake/backend/core/src/Twake/Workspaces/Services/Workspaces.php index d96d806daa..eef3b5c3a1 100755 --- a/twake/backend/core/src/Twake/Workspaces/Services/Workspaces.php +++ b/twake/backend/core/src/Twake/Workspaces/Services/Workspaces.php @@ -141,7 +141,7 @@ public function create($name, $groupId = null, $userId = null, $default = false) "name" => "General", "description" => "", "visibility" => "public", - "default" => true + "is_default" => true ], "options" => [], "user_id" => $userId diff --git a/twake/backend/node/src/cli/cmds/generate_cmds/users-and-companies.ts b/twake/backend/node/src/cli/cmds/generate_cmds/users-and-companies.ts index 2da1730c91..e10ce7b82c 100644 --- a/twake/backend/node/src/cli/cmds/generate_cmds/users-and-companies.ts +++ b/twake/backend/node/src/cli/cmds/generate_cmds/users-and-companies.ts @@ -117,10 +117,10 @@ const getUsers = (company: Company, size: number = 100): User[] => { const getUser = (company: Company, id: number): User => { return getUserInstance({ id: uuid(), - firstname: "John", - lastname: `Doe${id}`, - emailcanonical: `user${id}@${company.name}`, - creationdate: Date.now(), + first_name: "John", + last_name: `Doe${id}`, + email_canonical: `user${id}@${company.name}`, + creation_date: Date.now(), password: passwordGenerator.generate({ length: 10, numbers: true, diff --git a/twake/backend/node/src/core/platform/services/auth/web/jwt.ts b/twake/backend/node/src/core/platform/services/auth/web/jwt.ts index 98a71382e4..f4f42978ae 100644 --- a/twake/backend/node/src/core/platform/services/auth/web/jwt.ts +++ b/twake/backend/node/src/core/platform/services/auth/web/jwt.ts @@ -12,7 +12,12 @@ const jwtPlugin: FastifyPluginCallback = (fastify, _opts, next) => { fastify.decorate("authenticate", async (request: FastifyRequest) => { try { const jwt: JwtType = await request.jwtVerify(); - request.currentUser = { ...{ org: jwt.org }, ...{ email: jwt.email }, ...{ id: jwt.sub } }; + request.currentUser = { + ...{ org: jwt.org }, + ...{ email: jwt.email }, + ...{ id: jwt.sub }, + ...{ identity_provider_id: jwt.provider_id }, + }; request.log.debug(`Authenticated as user ${request.currentUser.id}`); } catch (err) { throw fastify.httpErrors.unauthorized("Bad credentials"); diff --git a/twake/backend/node/src/core/platform/services/tracker/index.ts b/twake/backend/node/src/core/platform/services/tracker/index.ts index 007275f7a6..f9a3c278c3 100644 --- a/twake/backend/node/src/core/platform/services/tracker/index.ts +++ b/twake/backend/node/src/core/platform/services/tracker/index.ts @@ -16,7 +16,7 @@ export default class Tracker extends TwakeService implements Tracker localEventBus.subscribe(channelListEvent, data => { logger.debug(`Tracker - New ${channelListEvent} event`); this.identify({ - userId: data.user.id, + userId: data.user.identity_provider_id || data.user.id, traits: { email: data.user.email || "", company: { diff --git a/twake/backend/node/src/core/platform/services/types/index.ts b/twake/backend/node/src/core/platform/services/types/index.ts index c44775d76f..47a25ff6af 100644 --- a/twake/backend/node/src/core/platform/services/types/index.ts +++ b/twake/backend/node/src/core/platform/services/types/index.ts @@ -1,5 +1,6 @@ export type JwtType = { sub: string; + provider_id: string; //Console sub email: string; nbf: number; refresh_nbf: number; diff --git a/twake/backend/node/src/core/platform/services/websocket/services/index.ts b/twake/backend/node/src/core/platform/services/websocket/services/index.ts index 5544961401..48d7b43afd 100644 --- a/twake/backend/node/src/core/platform/services/websocket/services/index.ts +++ b/twake/backend/node/src/core/platform/services/websocket/services/index.ts @@ -61,6 +61,7 @@ export class WebSocketService extends EventEmitter implements WebSocketAPI { getUser(socket: WebSocket): WebSocketUser { return { id: socket.decoded_token.sub, + identity_provider_id: socket.decoded_token.provider_id, email: socket.decoded_token.email, org: socket.decoded_token.org, token: socket.decoded_token, diff --git a/twake/backend/node/src/services/channels/entities/channel-activity.ts b/twake/backend/node/src/services/channels/entities/channel-activity.ts index 6e93743e40..b3452322a2 100644 --- a/twake/backend/node/src/services/channels/entities/channel-activity.ts +++ b/twake/backend/node/src/services/channels/entities/channel-activity.ts @@ -27,9 +27,10 @@ export class ChannelActivity { last_activity: number; @Column("last_message", "encoded_json") - last_message: { + last_message: null | { date: number; sender: string; + sender_name: string; title: string; text: string; }; diff --git a/twake/backend/node/src/services/channels/provider.ts b/twake/backend/node/src/services/channels/provider.ts index 93cc927f25..8dedbdacc0 100644 --- a/twake/backend/node/src/services/channels/provider.ts +++ b/twake/backend/node/src/services/channels/provider.ts @@ -30,6 +30,7 @@ export type ChannelPrimaryKey = { export type ChannelActivityMessage = { date: number; sender: string; + sender_name: string; title: string; text: string; }; @@ -97,6 +98,7 @@ export interface ChannelService */ updateLastActivity( payload: { + date: number; channel: ChannelPrimaryKey; message: ChannelActivityMessage; }, diff --git a/twake/backend/node/src/services/channels/services/channel/service.ts b/twake/backend/node/src/services/channels/services/channel/service.ts index a98c6cb735..56cca565d4 100644 --- a/twake/backend/node/src/services/channels/services/channel/service.ts +++ b/twake/backend/node/src/services/channels/services/channel/service.ts @@ -316,8 +316,9 @@ export class Service implements ChannelService { }) async updateLastActivity( payload: { + date: number; channel: ChannelPrimaryKey; - message: ChannelActivityMessage; + message: ChannelActivityMessage | null; }, context: WorkspaceExecutionContext, ): Promise> { @@ -328,13 +329,16 @@ export class Service implements ChannelService { entity.channel_id = channelPK.id; entity.company_id = channelPK.company_id; entity.workspace_id = channelPK.workspace_id; - entity.last_activity = channelActivityMessage.date; - entity.last_message = { - date: channelActivityMessage.date, - sender: channelActivityMessage.sender, - title: channelActivityMessage.title, - text: channelActivityMessage.text, - }; + entity.last_activity = payload.date; + entity.last_message = channelActivityMessage + ? { + date: channelActivityMessage.date, + sender: channelActivityMessage.sender, + sender_name: channelActivityMessage.sender_name, + title: channelActivityMessage.title, + text: channelActivityMessage.text, + } + : null; entity.channel = channel; @@ -607,6 +611,15 @@ export class Service implements ChannelService { } } + this.updateLastActivity( + { + date: new Date().getTime(), + channel: channel, + message: null, + }, + context, + ); + localEventBus.publish("channel:created", { channel }); } } diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity/index.ts b/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity/index.ts index e3459128a7..ea125fccec 100644 --- a/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity/index.ts +++ b/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity/index.ts @@ -29,6 +29,7 @@ export class NewChannelActivityProcessor try { this.service.updateLastActivity( { + date: message.date, channel: { id: message.channel_id, workspace_id: message.workspace_id, @@ -37,8 +38,9 @@ export class NewChannelActivityProcessor message: { date: message.date, sender: message.sender, + sender_name: message.sender_name, title: message.title, - text: message.text, + text: message.body, }, }, { diff --git a/twake/backend/node/src/services/channels/types.ts b/twake/backend/node/src/services/channels/types.ts index 7bf61481d4..0e872a0ac0 100644 --- a/twake/backend/node/src/services/channels/types.ts +++ b/twake/backend/node/src/services/channels/types.ts @@ -50,4 +50,6 @@ export type ChannelActivityNotification = { sender: string; title: string; text: string; + sender_name: string; + body: string; }; diff --git a/twake/backend/node/src/services/console/index.ts b/twake/backend/node/src/services/console/index.ts index 6ee2b16b03..7b92885d78 100644 --- a/twake/backend/node/src/services/console/index.ts +++ b/twake/backend/node/src/services/console/index.ts @@ -1,16 +1,20 @@ +import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; import { TwakeService, Consumes } from "../../core/platform/framework"; import UserServiceAPI from "../user/api"; import { ConsoleServiceAPI } from "./api"; import { getService } from "./service"; -@Consumes(["user"]) +@Consumes(["user", "database"]) export default class ConsoleService extends TwakeService { version = "1"; name = "console"; private service: ConsoleServiceAPI; async doInit(): Promise { - this.service = getService(this.context.getProvider("user")); + this.service = getService( + this.context.getProvider("database"), + this.context.getProvider("user"), + ); return this; } diff --git a/twake/backend/node/src/services/console/processing/merge.ts b/twake/backend/node/src/services/console/processing/merge.ts index 7319bc80f3..50fe92ac6c 100644 --- a/twake/backend/node/src/services/console/processing/merge.ts +++ b/twake/backend/node/src/services/console/processing/merge.ts @@ -33,6 +33,7 @@ import { getInstance as getExternalGroupInstance } from "../../user/entities/ext import CompanyUser from "../../user/entities/company_user"; import { ConsoleHTTPClient } from "../client"; import { ConsoleServiceClient } from "../api"; +import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; const logger = getLogger("console.process.merge"); @@ -40,6 +41,7 @@ export class MergeProcess { private client: ConsoleServiceClient; constructor( + private database: DatabaseServiceAPI, private userService: UserServiceAPI, private dryRun: boolean, private consoleId: string = "console", @@ -240,6 +242,10 @@ export class MergeProcess { createdCompany = await this.client.createCompany({ code: company.id, displayName: company.displayName, + avatar: { + type: "url", + value: company.logo, + }, status: "active", }); @@ -275,24 +281,56 @@ export class MergeProcess { throw new Error(`User ${companyUser.user_id} not found`); } + const firstName = + user.first_name && user.first_name.trim().length ? user.first_name : user.email_canonical; + const lastName = + user.last_name && user.last_name.trim().length ? user.last_name : user.email_canonical; + const name = (firstName + " " + lastName).trim(); + + let role: "admin" | "guest" | "member" = + companyUser.level.valueOf() === 3 ? "admin" : "member"; + if (role != "admin") { + if (companyUser.isExterne) { + role = "guest"; + } + const workspacesUsers = await this.userService.workspaces.getAllForUser({ + userId: companyUser.user_id, + }); + workspacesUsers.getEntities().forEach(e => { + if (e.isExternal) { + role = "guest"; + } + }); + } + result = await this.client.addUser( { code: company.id }, { - email: user.emailcanonical, + email: user.email_canonical, // console requires that firstname/lastname are defined and at least 1 chat long - firstName: - user.firstname && user.firstname.trim().length ? user.firstname : user.emailcanonical, - lastName: - user.lastname && user.lastname.trim().length ? user.lastname : user.emailcanonical, + firstName, + lastName, + name, + avatar: { + type: "url", + value: user.picture, + }, password: passwordGenerator.generate({ length: 10, numbers: true, }), skipInvite: true, - role: companyUser.level.valueOf() === 3 ? "admin" : "member", + role, }, ); + const companyUserRepository = await this.database.getRepository( + "group_user", + CompanyUser, + ); + companyUser.role = role; + companyUserRepository.save(companyUser); + if (this.linkExternal) { await this.createUserLink(user, result, this.consoleId); } diff --git a/twake/backend/node/src/services/console/service.ts b/twake/backend/node/src/services/console/service.ts index 72482836bc..77ccb51434 100644 --- a/twake/backend/node/src/services/console/service.ts +++ b/twake/backend/node/src/services/console/service.ts @@ -1,3 +1,4 @@ +import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; import UserServiceAPI from "../user/api"; import { ConsoleServiceAPI } from "./api"; import { MergeProcess } from "./processing/merge"; @@ -6,7 +7,7 @@ import { MergeProgress } from "./types"; class ConsoleService implements ConsoleServiceAPI { version: "1"; - constructor(private userService: UserServiceAPI) {} + constructor(private database: DatabaseServiceAPI, private userService: UserServiceAPI) {} merge( baseUrl: string, @@ -17,7 +18,7 @@ class ConsoleService implements ConsoleServiceAPI { client: string, secret: string, ): MergeProgress { - return new MergeProcess(this.userService, dryRun, console, link, { + return new MergeProcess(this.database, this.userService, dryRun, console, link, { client, secret, url: baseUrl, @@ -25,6 +26,9 @@ class ConsoleService implements ConsoleServiceAPI { } } -export function getService(userService: UserServiceAPI): ConsoleServiceAPI { - return new ConsoleService(userService); +export function getService( + database: DatabaseServiceAPI, + userService: UserServiceAPI, +): ConsoleServiceAPI { + return new ConsoleService(database, userService); } diff --git a/twake/backend/node/src/services/console/types.ts b/twake/backend/node/src/services/console/types.ts index c486d7e2ca..5114f6bdc3 100644 --- a/twake/backend/node/src/services/console/types.ts +++ b/twake/backend/node/src/services/console/types.ts @@ -5,6 +5,10 @@ import CompanyUser from "../user/entities/company_user"; export interface CreateConsoleCompany { code: string; displayName: string; + avatar: { + type: "url"; + value: string; + }; country?: string; address?: string; logo?: string; @@ -25,6 +29,11 @@ export interface CreateConsoleUser { email: string; firstName: string; lastName: string; + name: string; + avatar: { + type: "url"; + value: string; + }; password: string; role: string; skipInvite: boolean; diff --git a/twake/backend/node/src/services/types/index.ts b/twake/backend/node/src/services/types/index.ts index bd4e386946..18d719eb17 100644 --- a/twake/backend/node/src/services/types/index.ts +++ b/twake/backend/node/src/services/types/index.ts @@ -40,6 +40,8 @@ export const webSocketSchema = { export interface User { // unique user id id: uuid; + // unique console user id + identity_provider_id?: uuid; // user email email?: string; // Organisation properties diff --git a/twake/backend/node/src/services/user/api.ts b/twake/backend/node/src/services/user/api.ts index cc9339d6aa..2984d7f308 100644 --- a/twake/backend/node/src/services/user/api.ts +++ b/twake/backend/node/src/services/user/api.ts @@ -101,6 +101,15 @@ export interface WorkspaceServiceAPI pagination?: Paginable, ): Promise>; + /** + * Get all the workspace for a user + * + * @param userId + */ + getAllForUser( + userId: Pick, + ): Promise>; + /** * Get all the users of a workspace as Observable * diff --git a/twake/backend/node/src/services/user/entities/company.ts b/twake/backend/node/src/services/user/entities/company.ts index d4c25c5a40..3e8599930b 100644 --- a/twake/backend/node/src/services/user/entities/company.ts +++ b/twake/backend/node/src/services/user/entities/company.ts @@ -25,6 +25,9 @@ export default class Company { stats: any; @Column("logo_id", "uuid") + logofile: string; + + @Column("logo", "string") logo: string; @Column("workspaces_id", "encoded_json") @@ -48,6 +51,12 @@ export default class Company { @Column("member_count", "number") memberCount: number; + + @Column("identity_provider", "encoded_string") + identity_provider: string; + + @Column("identity_provider_id", "encoded_string") + identity_provider_id: string; } export type CompanyPrimaryKey = Pick; diff --git a/twake/backend/node/src/services/user/entities/company_user.ts b/twake/backend/node/src/services/user/entities/company_user.ts index 840a46b960..d270c65218 100644 --- a/twake/backend/node/src/services/user/entities/company_user.ts +++ b/twake/backend/node/src/services/user/entities/company_user.ts @@ -21,18 +21,8 @@ export default class CompanyUser { @Column("id", "timeuuid") id: string; - /** - * 0: member, - * 1, 2, 3: admin, - */ - @Column("level", "number") - level: number; - - @Column("did_connect_today", "boolean") - didConnectToday: boolean; - - @Column("app_used_today", "json") - appUsedToday: Array; + @Column("role", "string") + role: "guest" | "admin" | "member"; @Column("nb_workspace", "number") nbWorkspaces: number; @@ -44,10 +34,26 @@ export default class CompanyUser { lastUpdateDay: number; @Column("nb_connections_period", "number") - nbConnectionsPeriod: number; + nbConnectionsPeriod: number; //Depreciated @Column("app_used_period", "number") - appUsedPeriod: number; + appUsedPeriod: number; //Depreciated + + /** + * 0: member, + * 1, 2, 3: admin, + */ + @Column("level", "number") + level: number; //Depreciated + + @Column("is_externe", "twake_boolean") + isExterne: boolean; //Depreciated + + @Column("did_connect_today", "twake_boolean") + didConnectToday: boolean; //Depreciated + + @Column("app_used_today", "json") + appUsedToday: Array; //Depreciated } export type CompanyUserPrimaryKey = Partial>; diff --git a/twake/backend/node/src/services/user/entities/user.ts b/twake/backend/node/src/services/user/entities/user.ts index 9a4e2688eb..35ade52791 100644 --- a/twake/backend/node/src/services/user/entities/user.ts +++ b/twake/backend/node/src/services/user/entities/user.ts @@ -11,72 +11,32 @@ export default class User { @Column("id", "timeuuid") id: string; - @Column("banned", "twake_boolean") - banned = false; - - @Column("is_robot", "twake_boolean") - isrobot = false; - @Column("first_name", "encoded_string") - firstname: string; + first_name: string; @Column("last_name", "encoded_string") - lastname: string; - - /** - * FIXME: This is a thumbnail_id in current user table - */ - @Column("thumbnail", "string") - thumbnail: string; - - @Column("workspaces", "encoded_json") - workspaces: Array; + last_name: string; - /** - * @ORM\Column(name="groups", type="twake_text") - * FIXME: Decode error, check the type, if JSON - */ - @Column("groups", "encoded_json") - groups: Array; - - @Column("connections", "number") - connections: number; - - @Column("connected", "twake_boolean") - connected: boolean; + @Column("picture", "string") + picture: string; // FIXME: Looks like this is an array stringified, need to check DB @Column("status_icon", "json") status_icon: string; // = '["", ""]'; @Column("last_activity", "number") - lastactivity: number; + last_activity: number; @Column("creation_date", "number") - creationdate: number; + creation_date: number; @Column("language", "string") - language = "en"; + language: string; @Column("notification_preference", "encoded_json") // FIXME= Which type to use with encoded json? This is an object at the end notification_preference: any; - @Column("notification_read_increment", "number") - notification_read_increment = 0; - - @Column("notification_write_increment", "number") - notification_write_increment = 0; - - @Column("workspaces_preference", "encoded_json") - workspaces_preference: any; - - @Column("tutorial_status", "encoded_json") - tutorial_status: any; - - @Column("phone", "encoded_string") - phone: string; - @Column("identity_provider", "encoded_string") identity_provider: string; @@ -86,55 +46,19 @@ export default class User { @Column("token_login", "encoded_string") token_login: string; - @Column("origin", "string") - origin: string; - - @Column("is_new", "twake_boolean") - isnew = true; - - @Column("mail_verified", "twake_boolean") - mail_verified = false; - - @Column("mail_verification_override", "string") - mail_verification_override: string; - // TODO: Index @Column("username_canonical", "string") - usernamecanonical: string; + username_canonical: string; // TODO: Index @Column("email_canonical", "string") - emailcanonical: string; - - @Column("remember_me_secret", "encoded_string") - remember_me_secret: string; - - @Column("enabled", "twake_boolean") - enabled: boolean; - - @Column("salt", "string") - salt: string; - - @Column("password", "string") - password: string; + email_canonical: string; @Column("timezone", "string") timezone: string; - // FIXME: This is a datetime - @Column("last_login", "number") - lastlogin: number; - - @Column("confirmation_token", "string") - confirmationtoken: string; - - // FIXME: This is a datetime - @Column("password_requested_at", "number") - passwordrequestedat: number; - - // FIXME: This is an array in PHP and looks like a:0:{} in the DB - @Column("roles", "json") - roles: Array; + @Column("password", "string") + password: string; constructor(id?: string) { this.id = id; diff --git a/twake/backend/node/src/services/user/entities/workspace.ts b/twake/backend/node/src/services/user/entities/workspace.ts index 26535f5b7e..a2ce944f63 100644 --- a/twake/backend/node/src/services/user/entities/workspace.ts +++ b/twake/backend/node/src/services/user/entities/workspace.ts @@ -4,7 +4,7 @@ import { Column, Entity } from "../../../core/platform/services/database/service export const TYPE = "workspace"; @Entity(TYPE, { - primaryKey: [["id"], "group_id", "id"], + primaryKey: [["group_id"], "id"], type: TYPE, }) export default class Workspace { @@ -14,33 +14,21 @@ export default class Workspace { @Column("name", "encoded_string") name: string; - @Column("logo", "uuid") + @Column("logo", "string") logo: string; - @Column("stats", "uuid") + @Column("stats", "encoded_string") stats: string; - @Column("isdeleted", "twake_boolean") + @Column("is_deleted", "boolean") isDeleted: boolean; - @Column("isarchived", "twake_boolean") + @Column("is_archived", "boolean") isArchived: boolean; - @Column("isdefault", "twake_boolean") + @Column("is_default", "boolean") isDefault: boolean; - @Column("uniquename", "encoded_string") - uniqueName: string; - - @Column("member_count", "number") - memberCount: number; - - @Column("guest_count", "number") - guestCount: number; - - @Column("pending_count", "number") - pendingCount: number; - @Column("date_added", "number") dateAdded: number; } diff --git a/twake/backend/node/src/services/user/entities/workspace_user.ts b/twake/backend/node/src/services/user/entities/workspace_user.ts index 1060fafa61..82981119c4 100644 --- a/twake/backend/node/src/services/user/entities/workspace_user.ts +++ b/twake/backend/node/src/services/user/entities/workspace_user.ts @@ -20,8 +20,8 @@ export default class WorkspaceUser { @Column("id", "timeuuid") id: string; - @Column("level_id", "number") - levelId: number; + @Column("role", "string") + role: "admin" | "member"; //Relative to workspace only (not relative to company) @Column("date_added", "number") dateAdded: number; @@ -29,14 +29,8 @@ export default class WorkspaceUser { @Column("last_access", "number") lastAccess: number; - @Column("hasnotifications", "twake_boolean") - hasNotifications: boolean; - @Column("is_externe", "twake_boolean") - isExternal: boolean; - - @Column("is_auto_add_externe", "twake_boolean") - autoAddExternalExternal: boolean; + isExternal: boolean; //Depreciated } export type WorkspaceUserPrimaryKey = Partial>; diff --git a/twake/backend/node/src/services/user/services/external_links/index.ts b/twake/backend/node/src/services/user/services/external_links/index.ts index f94d8250e6..6a77124a60 100644 --- a/twake/backend/node/src/services/user/services/external_links/index.ts +++ b/twake/backend/node/src/services/user/services/external_links/index.ts @@ -3,11 +3,15 @@ import Repository from "../../../../core/platform/services/database/services/orm import ExternalUser from "../../entities/external_user"; import ExternalGroup from "../../entities/external_company"; import { UserExternalLinksServiceAPI } from "../../api"; +import Company from "../../entities/company"; +import User from "../../entities/user"; export class UserExternalLinksService implements UserExternalLinksServiceAPI { version: "1"; private externalUserRepository: Repository; private externalGroupRepository: Repository; + private companyRepository: Repository; + private userRepository: Repository; constructor(private database: DatabaseServiceAPI) {} @@ -20,6 +24,8 @@ export class UserExternalLinksService implements UserExternalLinksServiceAPI { "external_group_repository", ExternalGroup, ); + this.companyRepository = await this.database.getRepository("group_entity", Company); + this.userRepository = await this.database.getRepository("user", User); return this; } @@ -27,12 +33,28 @@ export class UserExternalLinksService implements UserExternalLinksServiceAPI { async createExternalUser(user: ExternalUser): Promise { await this.externalUserRepository.save(user); + //Save user provider and provider id here + const internalUser = await this.userRepository.findOne({ id: user.user_id }); + if (internalUser) { + internalUser.identity_provider = user.service_id; + internalUser.identity_provider_id = user.external_id; + this.userRepository.save(internalUser); + } + return user; } async createExternalGroup(group: ExternalGroup): Promise { await this.externalGroupRepository.save(group); + //Save company provider and provider id here + const internalCompany = await this.companyRepository.findOne({ id: group.company_id }); + if (internalCompany) { + internalCompany.identity_provider = group.service_id; + internalCompany.identity_provider_id = group.external_id; + this.companyRepository.save(internalCompany); + } + return group; } } diff --git a/twake/backend/node/src/services/user/services/workspace/index.ts b/twake/backend/node/src/services/user/services/workspace/index.ts index c16a20117c..ba333bae85 100644 --- a/twake/backend/node/src/services/user/services/workspace/index.ts +++ b/twake/backend/node/src/services/user/services/workspace/index.ts @@ -88,6 +88,16 @@ export class WorkspaceService implements WorkspaceServiceAPI { ); } + getAllForUser( + userId: Pick, + pagination?: Paginable, + ): Promise> { + return this.workspaceUserRepository.find( + { user_id: userId.userId }, + { pagination: { limitStr: pagination?.limitStr, page_token: pagination?.page_token } }, + ); + } + getAllUsers$( workspaceId: Pick, pagination?: Paginable, diff --git a/twake/docker-compose.yml.dist b/twake/docker-compose.yml.dist.onpremise similarity index 71% rename from twake/docker-compose.yml.dist rename to twake/docker-compose.yml.dist.onpremise index 02c2aead31..12f6714739 100644 --- a/twake/docker-compose.yml.dist +++ b/twake/docker-compose.yml.dist.onpremise @@ -18,14 +18,10 @@ services: RABBITMQ_DEFAULT_PASS: admin node: - image: twaketech/twake-node - build: - context: ./backend/node - dockerfile: ../../docker/twake-node/Dockerfile.dev + image: twaketech/twake-node:latest environment: - NODE_ENV=production volumes: - - ./backend/node:/usr/src/app - ./configuration/backend-node/production.json:/usr/src/app/config/production.json depends_on: - scylladb @@ -34,14 +30,12 @@ services: - scylladb php: - image: twaketech/twake-php + image: twaketech/twake-php:latest environment: - - DEV=dev - build: - context: . - dockerfile: docker/twake-php/Dockerfile + - DEV=production volumes: - - ./backend/core/:/twake-core:cached + - ./configuration/backend/Parameters.php:/configuration/Parameters.php + - ./connectors/:/twake-core/src/BuiltInConnectors/Connectors - ./docker-data/drive/:/twake-core/drive/ - ./docker-data/fpm/:/etc/docker-data/fpm/ - ./docker-data/drive-preview/:/twake-core/web/medias/ @@ -53,13 +47,9 @@ services: - scylladb nginx: - image: twaketech/twake-nginx + image: twaketech/twake-nginx:latest environment: - - DEV=dev - #- MOBILE_HOST=http://node:3000 - build: - context: . - dockerfile: docker/twake-nginx/Dockerfile + - DEV=production ports: - 8000:80 depends_on: @@ -69,7 +59,6 @@ services: - php - node volumes: - - ./frontend/:/twake-react/ - ./docker-data/logs/nginx/:/var/log/nginx - ./docker-data/letsencrypt/:/etc/letsencrypt/ - ./docker-data/drive-preview/:/twake-core/web/medias/ diff --git a/twake/docker/twake-nginx/site.conf b/twake/docker/twake-nginx/site.conf index c36da7b884..a6433ea10a 100644 --- a/twake/docker/twake-nginx/site.conf +++ b/twake/docker/twake-nginx/site.conf @@ -31,14 +31,17 @@ server { } location ~ ^/internal/mobile/.* { + proxy_set_header X-Forwarded-Host $host; proxy_pass ${MOBILE_HOST}; } location ~ ^/(internal|plugins).* { + proxy_set_header X-Forwarded-Host $host; proxy_pass ${NODE_HOST}; } location ~ ^/(api|administration)/v2/.* { + proxy_set_header X-Forwarded-Host $host; proxy_pass ${NODE_HOST}; } diff --git a/twake/frontend/public/index.html b/twake/frontend/public/index.html index d85ec1b43d..0fadbc2703 100644 --- a/twake/frontend/public/index.html +++ b/twake/frontend/public/index.html @@ -41,9 +41,8 @@ } - - +
@@ -80,13 +79,7 @@ } - +