fix: check report access with the user id of the lists site
The user id differs per site, so the id from the page context showed "Нет доступа" in reports when the page was not on /sites/stroy. The id and the photo folder path now come from settings.siteUrl. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { IHttpClient } from './http/IHttpClient';
|
||||
import { createAadClient, createSharePointClient } from './http/spfxClients';
|
||||
import { DATAVERSE_URL, SITE_URL, TNSU_API_BASE_URL, TNSU_API_RESOURCE_ID } from '../config/constants';
|
||||
import { createCurrentUserIdProvider } from './siteUser';
|
||||
|
||||
/** Настройки подключения из property pane (пустое значение — берётся значение по умолчанию). */
|
||||
export interface IConnectionSettings {
|
||||
@@ -34,6 +35,12 @@ export interface IAppServices {
|
||||
tnsuApi: IHttpClient;
|
||||
settings: IResolvedSettings;
|
||||
page: IPageInfo;
|
||||
/**
|
||||
* Id текущего пользователя на сайте со списками (settings.siteUrl). Id пользователя у каждого сайта
|
||||
* свой: legacyPageContext.userId — это id на сайте страницы, и в workbench корневого сайта он не
|
||||
* совпадает с id в «Доступах» сайта stroy. Запрашивается один раз.
|
||||
*/
|
||||
getCurrentUserId: () => Promise<number>;
|
||||
}
|
||||
|
||||
function withoutTrailingSlash(url: string): string {
|
||||
@@ -60,11 +67,13 @@ function readPageInfo(context: WebPartContext): IPageInfo {
|
||||
|
||||
export function createAppServices(context: WebPartContext, settings: IConnectionSettings): IAppServices {
|
||||
const resolved = resolveSettings(settings);
|
||||
const sharePoint = createSharePointClient(context);
|
||||
return {
|
||||
sharePoint: createSharePointClient(context),
|
||||
sharePoint,
|
||||
dataverse: createAadClient(context, resolved.dataverseUrl),
|
||||
tnsuApi: createAadClient(context, TNSU_API_RESOURCE_ID),
|
||||
settings: resolved,
|
||||
page: readPageInfo(context)
|
||||
page: readPageInfo(context),
|
||||
getCurrentUserId: createCurrentUserIdProvider(sharePoint, resolved.siteUrl)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { createCurrentUserIdProvider, siteServerRelativeUrl } from './siteUser';
|
||||
import { createFakeHttpClient } from '../shared/testing/fakeHttpClient';
|
||||
|
||||
const SITE = 'https://tnsukz.sharepoint.com/sites/stroy';
|
||||
|
||||
describe('siteServerRelativeUrl', () => {
|
||||
it('путь сайта без домена', () => {
|
||||
expect(siteServerRelativeUrl(SITE)).toEqual('/sites/stroy');
|
||||
expect(siteServerRelativeUrl('https://tnsukz.sharepoint.com')).toEqual('/');
|
||||
});
|
||||
});
|
||||
|
||||
describe('createCurrentUserIdProvider', () => {
|
||||
it('спрашивает currentuser у сайта со списками (не у сайта страницы) и запоминает', async () => {
|
||||
const sharePoint = createFakeHttpClient([{ match: 'currentuser', response: { body: { Id: 19 } } }]);
|
||||
const getCurrentUserId = createCurrentUserIdProvider(sharePoint, SITE);
|
||||
|
||||
expect(await getCurrentUserId()).toEqual(19);
|
||||
expect(await getCurrentUserId()).toEqual(19);
|
||||
expect(sharePoint.requests).toHaveLength(1);
|
||||
expect(sharePoint.requests[0].url).toEqual(`${SITE}/_api/web/currentuser?$select=Id`);
|
||||
});
|
||||
|
||||
it('неудачный запрос не запоминается — следующий вызов спрашивает снова', async () => {
|
||||
const sharePoint = createFakeHttpClient([
|
||||
{ match: 'currentuser', respond: (call) => (call === 1 ? { status: 503 } : { body: { Id: 19 } }) }
|
||||
]);
|
||||
const getCurrentUserId = createCurrentUserIdProvider(sharePoint, SITE);
|
||||
|
||||
await expect(getCurrentUserId()).rejects.toThrow('503');
|
||||
expect(await getCurrentUserId()).toEqual(19);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { IHttpClient } from './http/IHttpClient';
|
||||
import { fetchCurrentUserId } from '../shared/sharepoint/spRest';
|
||||
|
||||
// Пользователь и пути — всегда относительно сайта со списками (settings.siteUrl), а не сайта страницы:
|
||||
// id пользователя у каждого сайта свой, и в workbench корневого сайта он не совпадает с id в «Доступах».
|
||||
|
||||
/** Серверный относительный путь сайта (`/sites/stroy`) — для путей к папкам библиотек. */
|
||||
export function siteServerRelativeUrl(siteUrl: string): string {
|
||||
return siteUrl.replace(/^https?:\/\/[^/]+/, '') || '/';
|
||||
}
|
||||
|
||||
/** Запоминает id пользователя; неудачный запрос не запоминается — следующий вызов спросит снова. */
|
||||
export function createCurrentUserIdProvider(sharePoint: IHttpClient, siteUrl: string): () => Promise<number> {
|
||||
let userIdPromise: Promise<number> | undefined;
|
||||
return () => {
|
||||
if (userIdPromise) return userIdPromise;
|
||||
const request = fetchCurrentUserId(sharePoint, siteUrl).catch((error: unknown) => {
|
||||
userIdPromise = undefined;
|
||||
throw error;
|
||||
});
|
||||
userIdPromise = request;
|
||||
return request;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user