Skip to content
Merged
7 changes: 7 additions & 0 deletions core/js/tests/specHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ window._oc_appswebroots = {
"files": window.webroot + '/apps/files/',
"files_sharing": window.webroot + '/apps/files_sharing/'
};

window.OC ??= {};

OC.config = {
session_lifetime: 600 * 1000,
session_keepalive: false,
Expand All @@ -111,6 +114,10 @@ window.Snap.prototype = {

window.isPhantom = /phantom/i.test(navigator.userAgent);
document.documentElement.lang = navigator.language;
const el = document.createElement('input');
el.id = 'initial-state-core-config';
el.value = btoa(JSON.stringify(window.OC.config))
document.body.append(el);

// global setup for all tests
(function setupTests() {
Expand Down
87 changes: 0 additions & 87 deletions core/js/tests/specs/coreSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,93 +119,6 @@ describe('Core base tests', function() {
})).toEqual('number=123');
});
});
describe('Session heartbeat', function() {
var clock,
oldConfig,
counter;

beforeEach(function() {
clock = sinon.useFakeTimers();
oldConfig = OC.config;
counter = 0;

fakeServer.autoRespond = true;
fakeServer.autoRespondAfter = 0;
fakeServer.respondWith(/\/csrftoken/, function(xhr) {
counter++;
xhr.respond(200, {'Content-Type': 'application/json'}, '{"token": "pgBEsb3MzTb1ZPd2mfDZbQ6/0j3OrXHMEZrghHcOkg8=:3khw5PSa+wKQVo4f26exFD3nplud9ECjJ8/Y5zk5/k4="}');
});
$(document).off('ajaxComplete'); // ignore previously registered heartbeats
});
afterEach(function() {
clock.restore();
/* jshint camelcase: false */
OC.config = oldConfig;
$(document).off('ajaxError');
$(document).off('ajaxComplete');
});
it('sends heartbeat half the session lifetime when heartbeat enabled', function() {
/* jshint camelcase: false */
OC.config = {
session_keepalive: true,
session_lifetime: 300
};
window.initCore();

expect(counter).toEqual(0);

// less than half, still nothing
clock.tick(100 * 1000);
expect(counter).toEqual(0);

// reach past half (160), one call
clock.tick(55 * 1000);
expect(counter).toEqual(1);

// almost there to the next, still one
clock.tick(140 * 1000);
expect(counter).toEqual(1);

// past it, second call
clock.tick(20 * 1000);
expect(counter).toEqual(2);
});
it('does not send heartbeat when heartbeat disabled', function() {
/* jshint camelcase: false */
OC.config = {
session_keepalive: false,
session_lifetime: 300
};
window.initCore();

expect(counter).toEqual(0);

clock.tick(1000000);

// still nothing
expect(counter).toEqual(0);
});
it('limits the heartbeat between one minute and one day', function() {
/* jshint camelcase: false */
var setIntervalStub = sinon.stub(window, 'setInterval');
OC.config = {
session_keepalive: true,
session_lifetime: 5
};
window.initCore();
expect(setIntervalStub.getCall(0).args[1]).toEqual(60 * 1000);
setIntervalStub.reset();

OC.config = {
session_keepalive: true,
session_lifetime: 48 * 3600
};
window.initCore();
expect(setIntervalStub.getCall(0).args[1]).toEqual(24 * 3600 * 1000);

setIntervalStub.restore();
});
});
describe('Parse query string', function() {
it('Parses query string from full URL', function() {
var query = OC.parseQueryString('http://localhost/stuff.php?q=a&b=x');
Expand Down
2 changes: 1 addition & 1 deletion core/src/OC/eventsource.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/* eslint-disable */
import $ from 'jquery'

import { getToken } from './requesttoken.js'
import { getToken } from './requesttoken.ts'

/**
* Create a new event source
Expand Down
4 changes: 1 addition & 3 deletions core/src/OC/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ import {
getPort,
getProtocol,
} from './host.js'
import {
getToken as getRequestToken,
} from './requesttoken.js'
import { getRequestToken } from './requesttoken.ts'
import {
hideMenus,
registerMenu,
Expand Down
39 changes: 0 additions & 39 deletions core/src/OC/requesttoken.js

This file was deleted.

49 changes: 49 additions & 0 deletions core/src/OC/requesttoken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import { emit } from '@nextcloud/event-bus'
import { generateUrl } from '@nextcloud/router'

/**
* Get the current CSRF token.
*/
export function getRequestToken(): string {
return document.head.dataset.requesttoken!
}

/**
* Set a new CSRF token (e.g. because of session refresh).
* This also emits an event bus event for the updated token.
*
* @param token - The new token
* @fires Error - If the passed token is not a potential valid token
*/
export function setRequestToken(token: string): void {
if (!token || typeof token !== 'string') {
throw new Error('Invalid CSRF token given', { cause: { token } })
}

document.head.dataset.requesttoken = token
emit('csrf-token-update', { token })
}

/**
* Fetch the request token from the API.
* This does also set it on the current context, see `setRequestToken`.
*
* @fires Error - If the request failed
*/
export async function fetchRequestToken(): Promise<string> {
const url = generateUrl('/csrftoken')

const response = await fetch(url)
if (!response.ok) {
throw new Error('Could not fetch CSRF token from API', { cause: response })
}

const { token } = await response.json()
setRequestToken(token)
return token
}
2 changes: 1 addition & 1 deletion core/src/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import 'strengthify/strengthify.css'
import OC from './OC/index.js'
import OCP from './OCP/index.js'
import OCA from './OCA/index.js'
import { getToken as getRequestToken } from './OC/requesttoken.js'
import { getRequestToken } from './OC/requesttoken.ts'

const warnIfNotTesting = function() {
if (window.TESTING === undefined) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import _ from 'underscore'
import $ from 'jquery'
import moment from 'moment'

import { initSessionHeartBeat } from './session-heartbeat.js'
import OC from './OC/index.js'
import { initSessionHeartBeat } from './session-heartbeat.ts'
import { setUp as setUpContactsMenu } from './components/ContactsMenu.js'
import { setUp as setUpMainMenu } from './components/MainMenu.js'
import { setUp as setUpUserMenu } from './components/UserMenu.js'
Expand Down
4 changes: 2 additions & 2 deletions core/src/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import $ from 'jquery'
import { translate as t } from '@nextcloud/l10n'
import { linkTo } from '@nextcloud/router'

import { getToken } from './OC/requesttoken.js'
import { getRequestToken } from './OC/requesttoken.ts'
import getURLParameter from './Util/get-url-parameter.js'

import './jquery/showpassword.js'
Expand Down Expand Up @@ -140,7 +140,7 @@ window.addEventListener('DOMContentLoaded', function() {
t('core', 'Strong password'),
],
drawTitles: true,
nonce: btoa(getToken()),
nonce: btoa(getRequestToken()),
})

$('#dbpass').showPassword().keyup()
Expand Down
4 changes: 2 additions & 2 deletions core/src/jquery/requesttoken.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

import $ from 'jquery'

import { getToken } from '../OC/requesttoken.js'
import { getRequestToken } from '../OC/requesttoken.ts'

$(document).on('ajaxSend', function(elm, xhr, settings) {
if (settings.crossDomain === false) {
xhr.setRequestHeader('requesttoken', getToken())
xhr.setRequestHeader('requesttoken', getRequestToken())
xhr.setRequestHeader('OCS-APIREQUEST', 'true')
}
})
Loading
Loading