Skip to content

Commit 14ec6c4

Browse files
doublefacedoubleface
doubleface
authored andcommitted
fix(konnectors): Avoid creating multiple konnector folders
When the account folder already exist and has konnector reference and not the konnector folder
1 parent c6762bb commit 14ec6c4

File tree

4 files changed

+236
-29
lines changed

4 files changed

+236
-29
lines changed

docs/api/cozy-client/modules/models.konnectorFolder.md

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ The result path
4444

4545
*Defined in*
4646

47-
[packages/cozy-client/src/models/konnectorFolder.js:154](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L154)
47+
[packages/cozy-client/src/models/konnectorFolder.js:158](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L158)
4848

4949
***
5050

@@ -69,7 +69,47 @@ Permission object
6969

7070
*Defined in*
7171

72-
[packages/cozy-client/src/models/konnectorFolder.js:266](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L266)
72+
[packages/cozy-client/src/models/konnectorFolder.js:314](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L314)
73+
74+
***
75+
76+
### buildMainFolderPath
77+
78+
**buildMainFolderPath**(`konnector`, `magicFolders?`): `string`
79+
80+
Build konnector main folder path for a given konnector.
81+
82+
If konnector.folders\[0].defaultDir exists, it is used as default directory.
83+
84+
Occurrences of following strings in base directory are replaced by:
85+
86+
* `$administrative`: Administrative folder
87+
* `$photos`: Photos folder
88+
89+
Occurrences of following strings in path are replaced by:
90+
91+
* `$konnector`: Konnector name
92+
93+
If no konnectors.folders\[0].defaultDir is set, the default dir used is
94+
95+
* `$administrative/$konnector`
96+
97+
*Parameters*
98+
99+
| Name | Type | Description |
100+
| :------ | :------ | :------ |
101+
| `konnector` | `IOCozyKonnector` | Konnector document |
102+
| `magicFolders` | `Object` | Object containing a mapping from folder identifiers (ex: $administrative) to their localized values (ex: Administratif). |
103+
104+
*Returns*
105+
106+
`string`
107+
108+
The result path
109+
110+
*Defined in*
111+
112+
[packages/cozy-client/src/models/konnectorFolder.js:204](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L204)
73113

74114
***
75115

@@ -94,7 +134,7 @@ Directory attributes
94134

95135
*Defined in*
96136

97-
[packages/cozy-client/src/models/konnectorFolder.js:102](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L102)
137+
[packages/cozy-client/src/models/konnectorFolder.js:107](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L107)
98138

99139
***
100140

@@ -145,7 +185,7 @@ try to find a konnector account folder using file references
145185

146186
*Defined in*
147187

148-
[packages/cozy-client/src/models/konnectorFolder.js:374](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L374)
188+
[packages/cozy-client/src/models/konnectorFolder.js:422](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L422)
149189

150190
***
151191

@@ -172,4 +212,4 @@ Created io.cozy.files document
172212

173213
*Defined in*
174214

175-
[packages/cozy-client/src/models/konnectorFolder.js:117](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L117)
215+
[packages/cozy-client/src/models/konnectorFolder.js:122](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/models/konnectorFolder.js#L122)

packages/cozy-client/src/models/konnectorFolder.js

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@ const DEFAULT_LOCALIZED_BASE_DIR = 'Administrative'
2121
* @param {Object} options - options object
2222
* @param {import('../types').IOCozyKonnector} options.konnector - io.cozy.konnectors document
2323
* @param {import('../types').IOCozyAccount} options.account - io.cozy.accounts document
24-
* @param {String} options.lang - instance current language. ex: 'fr'
24+
* @param {string} options.lang - instance current language. ex: 'fr'
2525
* @returns {Promise<import('../types').IOCozyFolder>}
2626
*/
2727
export const ensureKonnectorFolder = async (
2828
client,
2929
{ konnector, account, lang }
3030
) => {
3131
const permissions = client.collection(PERMISSIONS_DOCTYPE)
32-
const fileCollection = client.collection(FILES_DOCTYPE)
33-
3432
const t = getLocalizer(lang)
3533
const [adminFolder, photosFolder] = await Promise.all([
3634
ensureMagicFolder(
@@ -64,6 +62,19 @@ export const ensureKonnectorFolder = async (
6462
})
6563
}
6664

65+
const mainPath = buildMainFolderPath(konnector, {
66+
administrative: adminFolder.path,
67+
photos: photosFolder.path
68+
})
69+
const mainFolder =
70+
(await statDirectoryByPath(client, mainPath)) ||
71+
(await createDirectoryByPath(client, mainPath))
72+
73+
ensureKonnectorReference({
74+
client,
75+
folder: mainFolder,
76+
konnector
77+
})
6778
// if the previous shortcuts did not work, create the folders like we did before but with proper references
6879
const path = buildFolderPath(konnector, account, {
6980
administrative: adminFolder.path,
@@ -73,19 +84,13 @@ export const ensureKonnectorFolder = async (
7384
(await statDirectoryByPath(client, path)) ||
7485
(await createDirectoryByPath(client, path))
7586

76-
const { data: konnectorFolder } = await fileCollection.statById(folder.dir_id)
7787
await Promise.all([
7888
permissions.add(konnector, buildFolderPermission(folder)),
7989
ensureKonnectorReference({ client, folder, konnector }),
8090
ensureSourceAccountIdentifierReference({
8191
client,
8292
folder,
8393
sourceAccountIdentifier
84-
}),
85-
ensureKonnectorReference({
86-
client,
87-
folder: konnectorFolder,
88-
konnector
8994
})
9095
])
9196

@@ -148,9 +153,8 @@ export const statDirectoryByPath = async (client, path) => {
148153
* @param {Object<string, string>} magicFolders Object containing a mapping from folder
149154
* identifiers (ex: $administrative) to their localized values (ex:
150155
* Administratif).
151-
* @returns {String} The result path
156+
* @returns {string} The result path
152157
*/
153-
154158
export const buildFolderPath = (konnector, account, magicFolders = {}) => {
155159
const fullPath =
156160
konnector?.folders?.[0]?.defaultDir || '$administrative/$konnector/$account'
@@ -178,10 +182,54 @@ export const buildFolderPath = (konnector, account, magicFolders = {}) => {
178182
return `/${renderedBaseDir}/${renderedPath}`
179183
}
180184

185+
/**
186+
* Build konnector main folder path for a given konnector.
187+
*
188+
* If konnector.folders[0].defaultDir exists, it is used as default directory.
189+
*
190+
* Occurrences of following strings in base directory are replaced by:
191+
* * `$administrative`: Administrative folder
192+
* * `$photos`: Photos folder
193+
*
194+
* Occurrences of following strings in path are replaced by:
195+
* * `$konnector`: Konnector name
196+
*
197+
* If no konnectors.folders[0].defaultDir is set, the default dir used is
198+
* * `$administrative/$konnector`
199+
*
200+
* @param {import('../types').IOCozyKonnector} konnector - Konnector document
201+
* @param {Object<string, string>} magicFolders - Object containing a mapping from folder identifiers (ex: $administrative) to their localized values (ex: Administratif).
202+
* @returns {string} The result path
203+
*/
204+
export const buildMainFolderPath = (konnector, magicFolders = {}) => {
205+
const fullPath =
206+
konnector?.folders?.[0]?.defaultDir
207+
?.split('/')
208+
?.slice(0, -1)
209+
?.join('/') || '$administrative/$konnector'
210+
let sanitizedPath = trim(fullPath.replace(/(\/+)/g, '/'), '/')
211+
if (!hasBaseDir(sanitizedPath)) {
212+
sanitizedPath = '$administrative/' + sanitizedPath
213+
}
214+
/**
215+
* Now that we have our sanitizedPath, we can split it in two strings
216+
* * `baseDir` containing the baseDir path
217+
* * `buildedSubDir` containing the rest of the path (ie the path without baseDir)
218+
*/
219+
const baseDir = sanitizedPath.split('/', 1)
220+
const buildedSubDir = buildSubDir(sanitizedPath, baseDir[0])
221+
222+
const renderedBaseDir = renderBaseDir(baseDir[0], magicFolders)
223+
const renderedPath = renderSubDir(buildedSubDir, {
224+
konnector: konnector.name
225+
})
226+
return `/${renderedBaseDir}/${renderedPath}`
227+
}
228+
181229
/**
182230
* Check if the provided Path start withs our allowedBaseDirPath to see
183231
*
184-
* @param {String} path - path to test
232+
* @param {string} path - path to test
185233
* @returns {Boolean}
186234
*/
187235
const hasBaseDir = path => {
@@ -200,9 +248,9 @@ const allowedBaseDirVariables = ['$administrative', '$photos']
200248
* This method creates the subDir. We can't have an empty subDir, so we set
201249
* it to our default '$konnector/$account'
202250
*
203-
* @param {String} fullPath String containing potentially the defaultDir
204-
* @param {String} defaultDir String to remove from the fullPath
205-
* @returns {String}
251+
* @param {string} fullPath String containing potentially the defaultDir
252+
* @param {string} defaultDir String to remove from the fullPath
253+
* @returns {string}
206254
*/
207255
const buildSubDir = (fullPath, defaultDir) => {
208256
let buildedSubDir = fullPath.substring(defaultDir.length)
@@ -217,11 +265,11 @@ const buildSubDir = (fullPath, defaultDir) => {
217265
* For example, it will render `$administrative` with the given value passed in
218266
* folders object. We expect to find in folders a localized value.
219267
*
220-
* @param {String} baseDir base directory variable, expects `$administrative`
268+
* @param {string} baseDir base directory variable, expects `$administrative`
221269
* or `$photos`
222270
* @param {Object<string, string>} magicFolders Object indexing base directory variable with
223271
* corresponding localized name.
224-
* @returns {String} Localized directory
272+
* @returns {string} Localized directory
225273
*/
226274
const renderBaseDir = (baseDir, magicFolders = {}) => {
227275
// Look for variable name into folders but without $ prefix
@@ -236,11 +284,11 @@ const renderBaseDir = (baseDir, magicFolders = {}) => {
236284
* Available variable are `$konnector` (konnector name) and `$account`
237285
* (account label, i.e. id or name)
238286
*
239-
* @param {String} path Path to render : ex '/Administratif/$konnector/$account'
287+
* @param {string} path Path to render : ex '/Administratif/$konnector/$account'
240288
* @param {Object} variables Object mapping variable to actual values
241289
* @param {import('../types').IOCozyKonnector['name']} variables.konnector - konnector name
242-
* @param {String} variables.account - account name
243-
* @returns {String} Rendered path
290+
* @param {string} [variables.account] - account name
291+
* @returns {string} Rendered path
244292
*/
245293
const renderSubDir = (path, variables) => {
246294
// Trim `/` and avoid multiple `/` characters with regexp
@@ -277,9 +325,9 @@ export const buildFolderPermission = folder => {
277325
/**
278326
* Replacer of the lodash/trim function
279327
*
280-
* @param {String} str - Input string
281-
* @param {String} c - String to trim from the input string
282-
* @returns {String}
328+
* @param {string} str - Input string
329+
* @param {string} c - String to trim from the input string
330+
* @returns {string}
283331
*/
284332
const trim = (str, c = '\\s') =>
285333
str.replace(new RegExp(`^([${c}]*)(.*?)([${c}]*)$`), '$2')

0 commit comments

Comments
 (0)