From 1c04825367e7873975ea572940a12d3411739cfb Mon Sep 17 00:00:00 2001 From: Dat Dang Date: Mon, 11 Aug 2025 09:30:09 +0700 Subject: [PATCH] Update Cozy integration doc (#3905) --- docs/adr/0061-cozy-integration-set-up.md | 36 ++++++- patchs/cozy-dev-config.patch | 120 +++++++++++++++++++++++ scripts/rlink.sh | 71 ++++++++++++++ 3 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 patchs/cozy-dev-config.patch create mode 100644 scripts/rlink.sh diff --git a/docs/adr/0061-cozy-integration-set-up.md b/docs/adr/0061-cozy-integration-set-up.md index 2f9a2053b..2131c5029 100644 --- a/docs/adr/0061-cozy-integration-set-up.md +++ b/docs/adr/0061-cozy-integration-set-up.md @@ -57,16 +57,46 @@ cozy-stack instances add tmail.localhost:8080 --passphrase cozy --apps home,stor 1. On the cozy-twakemail side - Clone `https://github.com/cozy/cozy-twakemail` - `yarn install` -- In `src/components/AppLayout.jsx`, replace `flag('mail.embedded-app-url')` with `http://localhost:2023` - `yarn build` - `cozy-stack serve --appdir tmail:build/ --disable-csp` +- Open another terminal while cozy-stack is running +- `cozy-stack apps install dataproxy --domain tmail.localhost:8080` +- `cozy-stack feature flags --domain tmail.localhost:8080 '{"cozy.search.enabled": true}'` +- `cozy-stack feature flags --domain tmail.localhost:8080 '{"mail.embedded-app-url": "http://localhost:2023"}'` 2. On the tmail side -- Config tmail to run on basic auth +- Apply patchs/cozy-dev-config.patch +- Edit session url in jmap-dart-client to /jmap/session - isInsideCozy will be `false` if run on localhost, so in cozy_config_web.dart, return true on isInsideCozy - in `env.file`, COZY_INTEGRATION=true - `flutter run -d chrome --web-port 2023 --web-browser-flag "--disable-web-security" --profile` 3. Access Cozy - tmail cozy: http://tmail.localhost:8080/ -- The password is `cozy` \ No newline at end of file +- The password is `cozy` + +### Run Cozy locally with modified Cozy libs +If there is a need of modifying Cozy libs +1. On cozy-libs side +- Clone `https://github.com/cozy/cozy-libs` +- `yarn install` +- `yarn build` +For example, if you want to use locally modified `cozy-external-bridge` +- `cd packages/cozy-external-bridge` +- `yarn link` +- `yarn build` + +2. On cozy-twakemail side +- Look for rlink.sh file in /scripts, move the file to ~/Downloads +- `mv ~/Downloads/rlink.sh ~/bin/rlink` +- `chmod +x ~/bin/rlink` +- Reset the terminal +- Repeat part 1 of `Run Cozy locally` +- While cozy-stack is running, open another terminal in the same directory +- `rlink {library-you-modified-and-linked}` for example `rlink cozy-external-bridge` +- While rlink is running, run `yarn build` + +3. On tmail side +- Repeat part 2 of `Run Cozy locally` + +Note: You can leave the cozy-stack and rlink running if you plan to further modify Cozy libs. After each modification, run `yarn build` in cozy-libs packages side then run `yarn build` in cozy-twakemail side, then refresh the browser. \ No newline at end of file diff --git a/patchs/cozy-dev-config.patch b/patchs/cozy-dev-config.patch new file mode 100644 index 000000000..30efb113e --- /dev/null +++ b/patchs/cozy-dev-config.patch @@ -0,0 +1,120 @@ +diff --git a/cozy/lib/cozy_config_manager/cozy_config_manager_web.dart b/cozy/lib/cozy_config_manager/cozy_config_manager_web.dart +index 03da73f1e..b518b19ef 100644 +--- a/cozy/lib/cozy_config_manager/cozy_config_manager_web.dart ++++ b/cozy/lib/cozy_config_manager/cozy_config_manager_web.dart +@@ -14,6 +14,7 @@ class CozyConfigManager { + } + + Future get isInsideCozy async { ++ return true; + return _isInsideCozy ??= await _checkCozyEnvironment(); + } + +diff --git a/env.file b/env.file +index 77b662611..2c60bb1a1 100644 +--- a/env.file ++++ b/env.file +@@ -1,6 +1,6 @@ +-SERVER_URL=http://localhost/ +-DOMAIN_REDIRECT_URL=http://localhost:3000 +-WEB_OIDC_CLIENT_ID=teammail-web ++SERVER_URL=https://jmap.lin-saas.dev ++DOMAIN_REDIRECT_URL=http://localhost:2023 ++WEB_OIDC_CLIENT_ID=teammail-web-dev + OIDC_SCOPES=openid,profile,email,offline_access + APP_GRID_AVAILABLE=supported + FCM_AVAILABLE=supported +@@ -8,4 +8,4 @@ IOS_FCM=supported + FORWARD_WARNING_MESSAGE= + PLATFORM=other + WS_ECHO_PING= +-COZY_INTEGRATION= +\ No newline at end of file ++COZY_INTEGRATION=true +\ No newline at end of file +diff --git a/lib/features/home/presentation/extensions/handle_web_finger_to_get_token_extension.dart b/lib/features/home/presentation/extensions/handle_web_finger_to_get_token_extension.dart +index a51b1a9d2..7d8734e0c 100644 +--- a/lib/features/home/presentation/extensions/handle_web_finger_to_get_token_extension.dart ++++ b/lib/features/home/presentation/extensions/handle_web_finger_to_get_token_extension.dart +@@ -2,11 +2,11 @@ import 'package:core/presentation/state/failure.dart'; + import 'package:core/utils/platform_info.dart'; + import 'package:dartz/dartz.dart'; + import 'package:model/oidc/oidc_configuration.dart'; +-import 'package:model/oidc/request/oidc_request.dart'; + import 'package:model/oidc/response/oidc_response.dart'; + import 'package:tmail_ui_user/features/home/presentation/home_controller.dart'; ++import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart'; + import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart'; +-import 'package:tmail_ui_user/features/login/domain/model/base_url_oidc_response.dart'; ++import 'package:tmail_ui_user/features/login/domain/state/check_oidc_is_available_state.dart'; + import 'package:tmail_ui_user/features/login/domain/state/get_oidc_configuration_state.dart'; + import 'package:tmail_ui_user/features/login/domain/state/get_token_oidc_state.dart'; + import 'package:tmail_ui_user/main/utils/app_config.dart'; +@@ -21,9 +21,7 @@ extension HandleWebFingerToGetTokenExtension on HomeController { + if (baseUri == null) { + goToLogin(); + } else { +- consumeState( +- checkOIDCIsAvailableInteractor.execute(OIDCRequest.fromUri(baseUri)), +- ); ++ handleFailureViewState(CheckOIDCIsAvailableFailure(CanNotFoundOIDCLinks())); + } + } + +@@ -58,7 +56,7 @@ extension HandleWebFingerToGetTokenExtension on HomeController { + } + + void tryGetOIDCConfigurationFromBaseUri(Uri baseUri) { +- getOIDCConfiguration(BaseUrlOidcResponse(baseUri)); ++ handleFailureViewState(GetOIDCConfigurationFromBaseUrlFailure(null)); + } + + bool isGetTokenOIDCFailure(Failure? failure) { +diff --git a/lib/features/login/presentation/extensions/handle_openid_configuration.dart b/lib/features/login/presentation/extensions/handle_openid_configuration.dart +index d8b35fd1b..f1c4ca3c4 100644 +--- a/lib/features/login/presentation/extensions/handle_openid_configuration.dart ++++ b/lib/features/login/presentation/extensions/handle_openid_configuration.dart +@@ -1,11 +1,11 @@ + +-import 'package:tmail_ui_user/features/login/domain/model/base_url_oidc_response.dart'; ++import 'package:tmail_ui_user/features/login/domain/state/get_oidc_configuration_state.dart'; + import 'package:tmail_ui_user/features/login/presentation/login_controller.dart'; + + extension HandleOpenidConfiguration on LoginController { + + void tryGetOIDCConfigurationFromBaseUrl(Uri baseUri) { +- getOIDCConfiguration(BaseUrlOidcResponse(baseUri)); ++ handleFailureViewState(GetOIDCConfigurationFromBaseUrlFailure(null)); + } + + void handleGetOIDCConfigurationFromBaseUrlFailure() { +diff --git a/lib/features/login/presentation/login_controller.dart b/lib/features/login/presentation/login_controller.dart +index ec41a9e7a..15b4864c6 100644 +--- a/lib/features/login/presentation/login_controller.dart ++++ b/lib/features/login/presentation/login_controller.dart +@@ -15,7 +15,6 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart'; + import 'package:jmap_dart_client/jmap/core/user_name.dart'; + import 'package:model/account/password.dart'; + import 'package:model/oidc/oidc_configuration.dart'; +-import 'package:model/oidc/request/oidc_request.dart'; + import 'package:model/oidc/response/oidc_response.dart'; + import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dart'; + import 'package:tmail_ui_user/features/home/domain/state/auto_sign_in_via_deep_link_state.dart'; +@@ -340,16 +339,7 @@ class LoginController extends ReloadableController { + } + + void _checkOIDCIsAvailable() { +- if (_currentBaseUrl == null) { +- dispatchState(Left(CheckOIDCIsAvailableFailure(CanNotFoundBaseUrl()))); +- } else { +- consumeState(_checkOIDCIsAvailableInteractor.execute( +- OIDCRequest( +- baseUrl: _currentBaseUrl!.toString(), +- resourceUrl: _currentBaseUrl!.origin +- ) +- )); +- } ++ handleFailureViewState(CheckOIDCIsAvailableFailure(CanNotFoundOIDCLinks())); + } + + void handleBackButtonAction(BuildContext context) { diff --git a/scripts/rlink.sh b/scripts/rlink.sh new file mode 100644 index 000000000..ece11bdaf --- /dev/null +++ b/scripts/rlink.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# rlink is useful when you are working in packages used in other packages/apps. Normally you +# would use yarn link but it can cause problems since node_modules are resolved inside the +# linked directory instead of the host directory. Here, the "link" is done the hard way with +# nodemon and rsync, ensuring that the node_modules/ corresponds to the linked package. +# Location of the linked packages is found by using the directory where yarn stores its symbolic +# links. +# +# ## Installation +# +# Assuming ~/bin is in your PATH +# $ wget https://gist.githubusercontent.com/ptbrowne/add609bdcf4396d32072acc4674fff23/raw -O ~/bin/rlink +# $ chmod +x ~/bin/rlink +# +# ## Usage +# +# `rlink cozy-client` + + +realpath=$(which realpath) +if [[ $realpath == "" ]]; then + realpath=$(which grealpath) +fi +if [[ $realpath == "" ]]; then + echo "You must have realpath (or grealpath) installed. `brew install coreutils` on mac osx." + exit 1 +fi + +which nodemon > /dev/null +if [[ $? != 0 ]]; then + echo "You must have nodemon installed globally" + exit 1 +fi + +set -e + +package=$1 + +if [[ $package == "" ]]; then + echo "Usage: rlink " + exit 1 +fi + +set -u + +package_link_dir=$($realpath ~/.config/yarn/link/$package) + + +if [[ -e $package_link_dir ]]; then + echo "$package is available in yarn links, resolved path is $package_link_dir" +else + echo "$package is not available in yarn links, please \`yarn link\` there first." + exit 1 +fi + +package_node_module_dir=$(pwd)/node_modules/$package + +if [[ -e $package_node_module_dir ]]; then + echo "$package is installed node_modules, resolved path is $package_node_module_dir" +else + echo "$package is not installed node_modules. Bailing out, please install the package first." + exit 1 +fi + +extensions="js,json,md,jsx,kt,java,m,mm,h,swift" + +echo "Will monitor extensions $extensions" +cmd="rsync -aP $package_link_dir/ --exclude .git --exclude node_modules $package_node_module_dir/" + +nodemon -w $package_link_dir -x "$cmd" -e $extensions