Add sync reset key bridge
This commit is contained in:
parent
a2791c494f
commit
35012025b6
|
|
@ -104,10 +104,12 @@ test.describe('D: Plugin API bridge', () => {
|
||||||
await api.sync.setInterval(15);
|
await api.sync.setInterval(15);
|
||||||
const configured = await api.sync.status();
|
const configured = await api.sync.status();
|
||||||
const syncNow = await api.sync.now();
|
const syncNow = await api.sync.now();
|
||||||
|
await api.sync.resetKey();
|
||||||
|
const reset = await api.sync.status();
|
||||||
await api.sync.disconnect();
|
await api.sync.disconnect();
|
||||||
const disconnected = await api.sync.status();
|
const disconnected = await api.sync.status();
|
||||||
api.dispose();
|
api.dispose();
|
||||||
return { initial, configured, syncNow, disconnected };
|
return { initial, configured, syncNow, reset, disconnected };
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.initial.statusLabel).toBe('disabled');
|
expect(result.initial.statusLabel).toBe('disabled');
|
||||||
|
|
@ -115,6 +117,10 @@ test.describe('D: Plugin API bridge', () => {
|
||||||
expect(result.configured.serverUrl).toBe('https://sync.example.test');
|
expect(result.configured.serverUrl).toBe('https://sync.example.test');
|
||||||
expect(result.configured.syncInterval).toBe(15);
|
expect(result.configured.syncInterval).toBe(15);
|
||||||
expect(result.syncNow).toEqual({ pushed: 0, pulled: 0, serverSequence: 0 });
|
expect(result.syncNow).toEqual({ pushed: 0, pulled: 0, serverSequence: 0 });
|
||||||
|
expect(result.reset.configured).toBe(false);
|
||||||
|
expect(result.reset.serverUrl).toBe('https://sync.example.test');
|
||||||
|
expect(result.reset.tokenStored).toBe(false);
|
||||||
|
expect(result.reset.statusLabel).toBe('disconnected');
|
||||||
expect(result.disconnected.configured).toBe(false);
|
expect(result.disconnected.configured).toBe(false);
|
||||||
expect(result.disconnected.statusLabel).toBe('disabled');
|
expect(result.disconnected.statusLabel).toBe('disabled');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,12 @@ export function createPluginAPI(pluginId) {
|
||||||
return App.PluginSyncSetInterval(pluginId, Number(minutes) || 0);
|
return App.PluginSyncSetInterval(pluginId, Number(minutes) || 0);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
resetKey: function() {
|
||||||
|
assertActive('sync.resetKey');
|
||||||
|
return callBackendErrorString(pluginId, 'sync.resetKey', function() {
|
||||||
|
return App.PluginSyncResetKey(pluginId);
|
||||||
|
});
|
||||||
|
},
|
||||||
now: function() {
|
now: function() {
|
||||||
assertActive('sync.now');
|
assertActive('sync.now');
|
||||||
return callBackend(pluginId, 'sync.now', function() {
|
return callBackend(pluginId, 'sync.now', function() {
|
||||||
|
|
|
||||||
|
|
@ -1116,6 +1116,22 @@
|
||||||
syncState.syncInterval = Number(minutes) || 0;
|
syncState.syncInterval = Number(minutes) || 0;
|
||||||
return Promise.resolve('');
|
return Promise.resolve('');
|
||||||
},
|
},
|
||||||
|
PluginSyncResetKey: function (pluginId) {
|
||||||
|
var err = requirePluginSyncPermission(pluginId, false);
|
||||||
|
if (err) return Promise.resolve(err);
|
||||||
|
syncState.configured = false;
|
||||||
|
syncState.deviceId = '';
|
||||||
|
syncState.deviceName = '';
|
||||||
|
syncState.connected = false;
|
||||||
|
syncState.revoked = false;
|
||||||
|
syncState.tokenStored = false;
|
||||||
|
syncState.lastError = '';
|
||||||
|
syncState.statusLabel = 'disconnected';
|
||||||
|
pluginSettings[pluginId] = Object.assign({}, pluginSettings[pluginId] || {}, {
|
||||||
|
syncStatus: syncState.statusLabel
|
||||||
|
});
|
||||||
|
return Promise.resolve('');
|
||||||
|
},
|
||||||
PluginSyncNow: function (pluginId) {
|
PluginSyncNow: function (pluginId) {
|
||||||
var err = requirePluginSyncPermission(pluginId, true);
|
var err = requirePluginSyncPermission(pluginId, true);
|
||||||
if (err) return Promise.resolve([{}, err]);
|
if (err) return Promise.resolve([{}, err]);
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ export function PluginSyncDisconnect(arg1:string):Promise<string>;
|
||||||
|
|
||||||
export function PluginSyncNow(arg1:string):Promise<Record<string, any>|string>;
|
export function PluginSyncNow(arg1:string):Promise<Record<string, any>|string>;
|
||||||
|
|
||||||
|
export function PluginSyncResetKey(arg1:string):Promise<string>;
|
||||||
|
|
||||||
export function PluginSyncSetInterval(arg1:string,arg2:number):Promise<string>;
|
export function PluginSyncSetInterval(arg1:string,arg2:number):Promise<string>;
|
||||||
|
|
||||||
export function PluginSyncStatus(arg1:string):Promise<api.SyncStatusDTO|string>;
|
export function PluginSyncStatus(arg1:string):Promise<api.SyncStatusDTO|string>;
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,10 @@ export function PluginSyncNow(arg1) {
|
||||||
return window['go']['api']['App']['PluginSyncNow'](arg1);
|
return window['go']['api']['App']['PluginSyncNow'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function PluginSyncResetKey(arg1) {
|
||||||
|
return window['go']['api']['App']['PluginSyncResetKey'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function PluginSyncSetInterval(arg1, arg2) {
|
export function PluginSyncSetInterval(arg1, arg2) {
|
||||||
return window['go']['api']['App']['PluginSyncSetInterval'](arg1, arg2);
|
return window['go']['api']['App']['PluginSyncSetInterval'](arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1550,6 +1550,8 @@ func (a *App) syncStatus() (*SyncStatusDTO, error) {
|
||||||
dto.StatusLabel = "connected"
|
dto.StatusLabel = "connected"
|
||||||
case dto.Configured:
|
case dto.Configured:
|
||||||
dto.StatusLabel = "disconnected"
|
dto.StatusLabel = "disconnected"
|
||||||
|
case dto.ServerURL != "":
|
||||||
|
dto.StatusLabel = "disconnected"
|
||||||
default:
|
default:
|
||||||
dto.StatusLabel = "disabled"
|
dto.StatusLabel = "disabled"
|
||||||
}
|
}
|
||||||
|
|
@ -1699,6 +1701,40 @@ func (a *App) PluginSyncSetInterval(pluginID string, minutes int) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) syncResetKey() error {
|
||||||
|
if err := a.requireVault(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
vaultPath := a.vaultPath()
|
||||||
|
if err := syncsvc.RemoveDeviceToken(vaultPath); err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := a.appSettings.Get()
|
||||||
|
cfg.Sync.Enabled = false
|
||||||
|
cfg.Sync.DeviceID = ""
|
||||||
|
cfg.Sync.DeviceName = ""
|
||||||
|
cfg.Sync.LastStatus = "disconnected"
|
||||||
|
cfg.Sync.LastError = ""
|
||||||
|
if a.syncSvc != nil {
|
||||||
|
if err := a.syncSvc.SetState(cfg.Sync.ServerURL, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a.appSettings.UpdateSync(cfg.Sync)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginSyncResetKey clears the stored sync device token for a plugin with sync permission.
|
||||||
|
func (a *App) PluginSyncResetKey(pluginID string) string {
|
||||||
|
if err := a.requirePluginSyncAccess(pluginID, false); err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
if err := a.syncResetKey(); err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) syncNow() (map[string]interface{}, error) {
|
func (a *App) syncNow() (map[string]interface{}, error) {
|
||||||
if err := a.requireVault(); err != nil {
|
if err := a.requireVault(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -1270,6 +1270,48 @@ func TestPluginSyncBridgeRequiresDeclaredPermissions(t *testing.T) {
|
||||||
if _, errStr := app.PluginSyncNow("sync.local"); !strings.Contains(errStr, "network.remote") {
|
if _, errStr := app.PluginSyncNow("sync.local"); !strings.Contains(errStr, "network.remote") {
|
||||||
t.Fatalf("PluginSyncNow err = %q, want network.remote permission error", errStr)
|
t.Fatalf("PluginSyncNow err = %q, want network.remote permission error", errStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.syncSvc = syncsvc.NewService(app.vaultPath(), "local-device")
|
||||||
|
app.appSettings = appsettings.NewManager(filepath.Join(t.TempDir(), "config.json"))
|
||||||
|
if err := app.appSettings.Load(); err != nil {
|
||||||
|
t.Fatalf("settings Load: %v", err)
|
||||||
|
}
|
||||||
|
cfg := app.appSettings.Get()
|
||||||
|
cfg.Sync.Enabled = true
|
||||||
|
cfg.Sync.ServerURL = "https://sync.example.test"
|
||||||
|
cfg.Sync.DeviceID = "device-1"
|
||||||
|
cfg.Sync.DeviceName = "test-device"
|
||||||
|
cfg.Sync.LastStatus = "connected"
|
||||||
|
if err := app.appSettings.UpdateSync(cfg.Sync); err != nil {
|
||||||
|
t.Fatalf("settings UpdateSync: %v", err)
|
||||||
|
}
|
||||||
|
if err := syncsvc.SaveDeviceToken(app.vaultPath(), "secret-token"); err != nil {
|
||||||
|
t.Fatalf("SaveDeviceToken: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errStr := app.PluginSyncResetKey("sync.local"); errStr != "" {
|
||||||
|
t.Fatalf("PluginSyncResetKey: %s", errStr)
|
||||||
|
}
|
||||||
|
if token := syncsvc.LoadDeviceToken(app.vaultPath()); token != "" {
|
||||||
|
t.Fatalf("device token = %q, want cleared", token)
|
||||||
|
}
|
||||||
|
cfg = app.appSettings.Get()
|
||||||
|
if cfg.Sync.DeviceID != "" || cfg.Sync.DeviceName != "" || cfg.Sync.LastStatus != "disconnected" {
|
||||||
|
t.Fatalf("sync settings after reset = %#v, want cleared device and disconnected status", cfg.Sync)
|
||||||
|
}
|
||||||
|
if cfg.Sync.ServerURL != "https://sync.example.test" {
|
||||||
|
t.Fatalf("server URL = %q, want preserved", cfg.Sync.ServerURL)
|
||||||
|
}
|
||||||
|
status, errStr = app.PluginSyncStatus("sync.local")
|
||||||
|
if errStr != "" {
|
||||||
|
t.Fatalf("PluginSyncStatus after reset: %s", errStr)
|
||||||
|
}
|
||||||
|
if status.Configured || status.ServerURL != "https://sync.example.test" || status.StatusLabel != "disconnected" {
|
||||||
|
t.Fatalf("status after reset = %#v, want server preserved, not configured, disconnected", status)
|
||||||
|
}
|
||||||
|
if errStr := app.PluginSyncResetKey("no.storage"); !strings.Contains(errStr, "sync.participate") {
|
||||||
|
t.Fatalf("PluginSyncResetKey err = %q, want sync.participate permission error", errStr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPluginBridgeCapabilitiesCommandsAndEventsAreChecked(t *testing.T) {
|
func TestPluginBridgeCapabilitiesCommandsAndEventsAreChecked(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue