Files
stroy-bot-monorepo/src/webparts/stroyBot/services/AppServices.ts
T
Тимур Городецкий f0272c2170 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>
2026-10-19 16:17:56 +05:00

80 lines
3.3 KiB
TypeScript

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 {
siteUrl?: string;
dataverseUrl?: string;
apiBaseUrl?: string;
}
export interface IResolvedSettings {
siteUrl: string;
dataverseUrl: string;
apiBaseUrl: string;
}
/** Сведения о текущей странице и пользователе из контекста SPFx. */
export interface IPageInfo {
/** Абсолютный URL сайта, на котором стоит web part. */
webAbsoluteUrl: string;
/** Серверный относительный URL сайта (`/sites/stroy`) — нужен для путей к папкам. */
webServerRelativeUrl: string;
/** Id пользователя в SharePoint этого сайта (legacyPageContext.userId). */
userId: number | undefined;
userDisplayName: string;
}
/** Всё, что нужно страницам для работы с данными. Создаётся в web part. */
export interface IAppServices {
sharePoint: IHttpClient;
dataverse: IHttpClient;
tnsuApi: IHttpClient;
settings: IResolvedSettings;
page: IPageInfo;
/**
* Id текущего пользователя на сайте со списками (settings.siteUrl). Id пользователя у каждого сайта
* свой: legacyPageContext.userId — это id на сайте страницы, и в workbench корневого сайта он не
* совпадает с id в «Доступах» сайта stroy. Запрашивается один раз.
*/
getCurrentUserId: () => Promise<number>;
}
function withoutTrailingSlash(url: string): string {
return url.replace(/\/+$/, '');
}
export function resolveSettings(settings: IConnectionSettings): IResolvedSettings {
return {
siteUrl: withoutTrailingSlash(settings.siteUrl || SITE_URL),
dataverseUrl: withoutTrailingSlash(settings.dataverseUrl || DATAVERSE_URL),
apiBaseUrl: withoutTrailingSlash(settings.apiBaseUrl || TNSU_API_BASE_URL)
};
}
function readPageInfo(context: WebPartContext): IPageInfo {
const legacyUserId: unknown = context.pageContext.legacyPageContext?.userId;
return {
webAbsoluteUrl: context.pageContext.web.absoluteUrl,
webServerRelativeUrl: context.pageContext.web.serverRelativeUrl,
userId: typeof legacyUserId === 'number' ? legacyUserId : undefined,
userDisplayName: context.pageContext.user.displayName
};
}
export function createAppServices(context: WebPartContext, settings: IConnectionSettings): IAppServices {
const resolved = resolveSettings(settings);
const sharePoint = createSharePointClient(context);
return {
sharePoint,
dataverse: createAadClient(context, resolved.dataverseUrl),
tnsuApi: createAadClient(context, TNSU_API_RESOURCE_ID),
settings: resolved,
page: readPageInfo(context),
getCurrentUserId: createCurrentUserIdProvider(sharePoint, resolved.siteUrl)
};
}