Skip to content

Commit

Permalink
[user-storage] enforce absolute URIs
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kosyakov <anton.kosyakov@typefox.io>
  • Loading branch information
akosyakov committed Jun 30, 2020
1 parent ca67699 commit f069ff7
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 29 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Breaking Changes:
- <a name="1_4_0_replace_json">[json]</a> replaced `@theia/json` Theia extension with `vscode.json-language-features` VS Code extension [#7972](https://github.com/eclipse-theia/theia/pull/7972)
- You can register JSON validations at application startup by implementing `JsonSchemaContribution` Theia contribution point.
- Alternatively you can provide JSON validations using VS Code [contributes.jsonValidation](https://code.visualstudio.com/api/references/contribution-points#contributes.jsonValidation) contribution point.
- <a name="1_4_0_absolute_user_storage_uri">[user-storage]</a> settings URI must be an absolute to satisfy expectations of `vscode.json-language-features` [#7972](https://github.com/eclipse-theia/theia/pull/7972)
- If you imlpement a custom user storage make sure to check old relaitve locations, otherwise it can cause user data loss.

## v1.3.0

Expand Down
2 changes: 1 addition & 1 deletion packages/keymaps/src/browser/keymaps-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class KeymapsService {
*/
@postConstruct()
protected async init(): Promise<void> {
this.resource = await this.resourceProvider(new URI().withScheme(UserStorageUri.SCHEME).withPath('keymaps.json'));
this.resource = await this.resourceProvider(new URI().withScheme(UserStorageUri.SCHEME).withPath('/keymaps.json'));
this.reconcile();
if (this.resource.onDidChangeContents) {
this.resource.onDidChangeContents(() => this.reconcile());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class UserConfigsPreferenceProvider extends PreferenceProvider {

protected createProviders(): void {
for (const configName of [...this.configurations.getSectionNames(), this.configurations.getConfigName()]) {
const sectionUri = USER_PREFERENCE_FOLDER.withPath(configName + '.json');
const sectionUri = USER_PREFERENCE_FOLDER.withPath('/' + configName + '.json');
const sectionKey = sectionUri.toString();
if (!this.providers.has(sectionKey)) {
const provider = this.createProvider(sectionUri, configName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { UserStorageUri } from '@theia/userstorage/lib/browser';
import { PreferenceScope } from '@theia/core/lib/browser';
import { SectionPreferenceProvider } from './section-preference-provider';

export const USER_PREFERENCE_URI = new URI().withScheme(UserStorageUri.SCHEME).withPath('settings.json');
export const USER_PREFERENCE_URI = new URI().withScheme(UserStorageUri.SCHEME).withPath('/settings.json');

export const UserPreferenceProviderFactory = Symbol('UserPreferenceProviderFactory');
export interface UserPreferenceProviderFactory {
Expand Down
2 changes: 1 addition & 1 deletion packages/userstorage/src/browser/user-storage-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class UserStorageResolver implements ResourceResolver {
) { }

resolve(uri: URI): MaybePromise<UserStorageResource> {
if (uri.scheme !== UserStorageUri.SCHEME) {
if (uri.scheme !== UserStorageUri.SCHEME || !uri.path.isAbsolute) {
throw new Error('The given uri is not a user storage uri: ' + uri);
}
return new UserStorageResource(uri, this.service);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,20 +128,20 @@ describe('User Storage Service (Filesystem implementation)', () => {

it('Should return a user storage uri from a filesystem uri', () => {

const test = UserStorageServiceFilesystemImpl.toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile));
const test = UserStorageServiceFilesystemImpl.toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile))!;
expect(test.scheme).eq(UserStorageUri.SCHEME);
expect(test.toString()).eq(UserStorageUri.SCHEME + ':' + testFile);
expect(test.toString()).eq(UserStorageUri.SCHEME + ':/' + testFile);

const testFragment = UserStorageServiceFilesystemImpl.
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile).withFragment('test'));
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile).withFragment('test'))!;
expect(testFragment.fragment).eq('test');

const testQuery = UserStorageServiceFilesystemImpl.
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile).withQuery('test=1'));
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile).withQuery('test=1'))!;
expect(testQuery.query).eq('test=1');

const testQueryAndFragment = UserStorageServiceFilesystemImpl.
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile).withQuery('test=1').withFragment('test'));
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile).withQuery('test=1').withFragment('test'))!;
expect(testQueryAndFragment.fragment).eq('test');
expect(testQueryAndFragment.query).eq('test=1');
});
Expand All @@ -157,7 +157,7 @@ describe('User Storage Service (Filesystem implementation)', () => {
userStorageService.onUserStorageChanged(event => {
const userStorageUri = event.uris[0];
expect(userStorageUri.scheme).eq(UserStorageUri.SCHEME);
expect(userStorageUri.path.toString()).eq(testFile);
expect(userStorageUri.path.toString()).eq('/' + testFile);
done();
});

Expand All @@ -173,7 +173,7 @@ describe('User Storage Service (Filesystem implementation)', () => {
it('Should save the contents correctly using a user storage uri to a filesystem uri', async () => {

const userStorageUri = UserStorageServiceFilesystemImpl.
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile));
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile))!;

await userStorageService.saveContents(userStorageUri, 'test content');

Expand All @@ -196,7 +196,7 @@ describe('User Storage Resource (Filesystem implementation)', () => {
testFile = 'test.json';
userStorageService = testContainer.get<UserStorageServiceFilesystemImpl>(UserStorageService);
const userStorageUriTest = UserStorageServiceFilesystemImpl.
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile));
toUserStorageUri(userStorageFolder, userStorageFolder.resolve(testFile))!;
userStorageResource = new UserStorageResource(userStorageUriTest, userStorageService);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ export class UserStorageServiceFilesystemImpl implements UserStorageService {
this.userStorageFolder.then(folder => {
if (folder) {
for (const change of event) {
if (folder.isEqualOrParent(change.uri)) {
const userStorageUri = UserStorageServiceFilesystemImpl.toUserStorageUri(folder, change.uri);
const userStorageUri = UserStorageServiceFilesystemImpl.toUserStorageUri(folder, change.uri);
if (userStorageUri) {
uris.push(userStorageUri);
}
}
Expand Down Expand Up @@ -108,20 +108,12 @@ export class UserStorageServiceFilesystemImpl implements UserStorageService {
* @param userStorageFolderUri User storage folder URI
* @param fsPath The filesystem URI
*/
public static toUserStorageUri(userStorageFolderUri: URI, rawUri: URI): URI {
const userStorageRelativePath = this.getRelativeUserStoragePath(userStorageFolderUri, rawUri);
return new URI('').withScheme(UserStorageUri.SCHEME).withPath(userStorageRelativePath).withFragment(rawUri.fragment).withQuery(rawUri.query);
}

/**
* Returns the path relative to the user storage filesystem uri i.e if the user storage root is
* 'file://home/user/.theia' and the fileUri is 'file://home/user.theia/keymaps.json' it will return 'keymaps.json'
* @param userStorageFolderUri User storage folder URI
* @param fileUri User storage
*/
private static getRelativeUserStoragePath(userStorageFolderUri: URI, fileUri: URI): string {
/* + 1 so that it removes the beginning slash i.e return keymaps.json and not /keymaps.json */
return fileUri.toString().slice(userStorageFolderUri.toString().length + 1);
public static toUserStorageUri(userStorageFolderUri: URI, rawUri: URI): URI | undefined {
const relativePath = userStorageFolderUri.relative(rawUri);
if (relativePath) {
return rawUri.withScheme(UserStorageUri.SCHEME).withPath('/' + relativePath);
}
return undefined;
}

/**
Expand All @@ -130,6 +122,6 @@ export class UserStorageServiceFilesystemImpl implements UserStorageService {
* @param userStorageUri User storage URI to be converted in filesystem URI
*/
public static toFilesystemURI(userStorageFolderUri: URI, userStorageUri: URI): URI {
return userStorageFolderUri.withPath(userStorageFolderUri.path.join(userStorageUri.path.toString()));
return userStorageFolderUri.resolve(userStorageUri.path).normalizePath();
}
}

0 comments on commit f069ff7

Please sign in to comment.