2026-03-20 16:43:44 +00:00
|
|
|
import * as plugins from './plugins.js';
|
|
|
|
|
import * as interfaces from '../ts_interfaces/index.js';
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Smartstate instance
|
|
|
|
|
// ============================================================================
|
|
|
|
|
export const appState = new plugins.domtools.plugins.smartstate.Smartstate();
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// State Part Interfaces
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
export interface ILoginState {
|
|
|
|
|
identity: interfaces.data.IIdentity | null;
|
|
|
|
|
isLoggedIn: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface IOrganizationsState {
|
|
|
|
|
organizations: interfaces.data.IOrganization[];
|
|
|
|
|
currentOrg: interfaces.data.IOrganizationDetail | null;
|
|
|
|
|
repositories: interfaces.data.IRepository[];
|
|
|
|
|
members: interfaces.data.IOrganizationMember[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface IPackagesState {
|
|
|
|
|
packages: interfaces.data.IPackage[];
|
|
|
|
|
currentPackage: interfaces.data.IPackageDetail | null;
|
|
|
|
|
versions: interfaces.data.IPackageVersion[];
|
|
|
|
|
total: number;
|
|
|
|
|
query: string;
|
|
|
|
|
protocolFilter: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ITokensState {
|
|
|
|
|
tokens: interfaces.data.IToken[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ISettingsState {
|
|
|
|
|
user: interfaces.data.IUser | null;
|
|
|
|
|
sessions: interfaces.data.ISession[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface IAdminState {
|
|
|
|
|
providers: interfaces.data.IAuthProvider[];
|
|
|
|
|
platformSettings: interfaces.data.IPlatformSettings | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface IUiState {
|
|
|
|
|
activeView: string;
|
|
|
|
|
activeEntityId?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// State Parts
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
export const loginStatePart = await appState.getStatePart<ILoginState>(
|
|
|
|
|
'login',
|
|
|
|
|
{
|
|
|
|
|
identity: null,
|
|
|
|
|
isLoggedIn: false,
|
|
|
|
|
},
|
|
|
|
|
'persistent',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const organizationsStatePart = await appState.getStatePart<IOrganizationsState>(
|
|
|
|
|
'organizations',
|
|
|
|
|
{
|
|
|
|
|
organizations: [],
|
|
|
|
|
currentOrg: null,
|
|
|
|
|
repositories: [],
|
|
|
|
|
members: [],
|
|
|
|
|
},
|
|
|
|
|
'soft',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const packagesStatePart = await appState.getStatePart<IPackagesState>(
|
|
|
|
|
'packages',
|
|
|
|
|
{
|
|
|
|
|
packages: [],
|
|
|
|
|
currentPackage: null,
|
|
|
|
|
versions: [],
|
|
|
|
|
total: 0,
|
|
|
|
|
query: '',
|
|
|
|
|
protocolFilter: '',
|
|
|
|
|
},
|
|
|
|
|
'soft',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const tokensStatePart = await appState.getStatePart<ITokensState>(
|
|
|
|
|
'tokens',
|
|
|
|
|
{ tokens: [] },
|
|
|
|
|
'soft',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const settingsStatePart = await appState.getStatePart<ISettingsState>(
|
|
|
|
|
'settings',
|
|
|
|
|
{ user: null, sessions: [] },
|
|
|
|
|
'soft',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const adminStatePart = await appState.getStatePart<IAdminState>(
|
|
|
|
|
'admin',
|
|
|
|
|
{ providers: [], platformSettings: null },
|
|
|
|
|
'soft',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const uiStatePart = await appState.getStatePart<IUiState>(
|
|
|
|
|
'ui',
|
|
|
|
|
{ activeView: 'dashboard' },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Helpers
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
const getActionContext = () => ({
|
|
|
|
|
identity: loginStatePart.getState().identity,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function createTypedRequest<T extends plugins.domtools.plugins.typedrequest.ITypedRequest>(
|
|
|
|
|
method: string,
|
|
|
|
|
) {
|
|
|
|
|
return new plugins.domtools.plugins.typedrequest.TypedRequest<T>('/typedrequest', method);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Auth Actions
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
export const loginAction = loginStatePart.createAction<{
|
|
|
|
|
email: string;
|
|
|
|
|
password: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_Login>('login');
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
email: dataArg.email,
|
|
|
|
|
password: dataArg.password,
|
|
|
|
|
});
|
|
|
|
|
if (response.identity) {
|
|
|
|
|
return { identity: response.identity, isLoggedIn: true };
|
|
|
|
|
}
|
|
|
|
|
return { identity: null, isLoggedIn: false };
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error('Login failed:', err);
|
|
|
|
|
return { identity: null, isLoggedIn: false };
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const logoutAction = loginStatePart.createAction(async () => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (context.identity) {
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_Logout>('logout');
|
|
|
|
|
await typedRequest.fire({ identity: context.identity });
|
|
|
|
|
} catch {
|
|
|
|
|
// Ignore logout errors
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return { identity: null, isLoggedIn: false };
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const refreshTokenAction = loginStatePart.createAction(async (statePartArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_RefreshToken>('refreshToken');
|
|
|
|
|
const response = await typedRequest.fire({ identity: context.identity });
|
|
|
|
|
return { identity: response.identity, isLoggedIn: true };
|
|
|
|
|
} catch {
|
|
|
|
|
return { identity: null, isLoggedIn: false };
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const fetchMeAction = settingsStatePart.createAction(async (statePartArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetMe>('getMe');
|
|
|
|
|
const response = await typedRequest.fire({ identity: context.identity });
|
|
|
|
|
return { ...statePartArg.getState(), user: response.user };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Handle OAuth callback tokens
|
|
|
|
|
export function handleOAuthCallback(
|
|
|
|
|
accessToken: string,
|
|
|
|
|
refreshToken: string,
|
|
|
|
|
sessionId: string,
|
|
|
|
|
) {
|
|
|
|
|
// Build a minimal identity from the callback tokens
|
|
|
|
|
// The full identity will be populated when getMe is called
|
|
|
|
|
loginStatePart.setState({
|
|
|
|
|
identity: {
|
|
|
|
|
jwt: accessToken,
|
|
|
|
|
refreshJwt: refreshToken,
|
|
|
|
|
userId: '',
|
|
|
|
|
email: '',
|
|
|
|
|
username: '',
|
|
|
|
|
displayName: '',
|
|
|
|
|
isSystemAdmin: false,
|
|
|
|
|
expiresAt: Date.now() + 900000,
|
|
|
|
|
sessionId,
|
|
|
|
|
},
|
|
|
|
|
isLoggedIn: true,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Organization Actions
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
export const fetchOrganizationsAction = organizationsStatePart.createAction(
|
|
|
|
|
async (statePartArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetOrganizations>(
|
|
|
|
|
'getOrganizations',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({ identity: context.identity });
|
|
|
|
|
return { ...statePartArg.getState(), organizations: response.organizations };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const fetchOrganizationAction = organizationsStatePart.createAction<{
|
|
|
|
|
organizationId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetOrganization>(
|
|
|
|
|
'getOrganization',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
organizationId: dataArg.organizationId,
|
|
|
|
|
});
|
|
|
|
|
return { ...statePartArg.getState(), currentOrg: response.organization };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const createOrganizationAction = organizationsStatePart.createAction<{
|
|
|
|
|
name: string;
|
|
|
|
|
displayName?: string;
|
|
|
|
|
description?: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_CreateOrganization>(
|
|
|
|
|
'createOrganization',
|
|
|
|
|
);
|
|
|
|
|
await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
name: dataArg.name,
|
|
|
|
|
displayName: dataArg.displayName,
|
|
|
|
|
description: dataArg.description,
|
|
|
|
|
});
|
|
|
|
|
// Re-fetch list
|
|
|
|
|
const listReq = createTypedRequest<interfaces.requests.IReq_GetOrganizations>(
|
|
|
|
|
'getOrganizations',
|
|
|
|
|
);
|
|
|
|
|
const listResp = await listReq.fire({ identity: context.identity });
|
|
|
|
|
return { ...statePartArg.getState(), organizations: listResp.organizations };
|
|
|
|
|
} catch {
|
2026-03-20 16:48:04 +00:00
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const updateOrganizationAction = organizationsStatePart.createAction<{
|
|
|
|
|
organizationId: string;
|
|
|
|
|
displayName?: string;
|
|
|
|
|
description?: string;
|
|
|
|
|
website?: string;
|
|
|
|
|
isPublic?: boolean;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_UpdateOrganization>(
|
|
|
|
|
'updateOrganization',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
...dataArg,
|
|
|
|
|
});
|
|
|
|
|
// Update the current org in state
|
|
|
|
|
return { ...statePartArg.getState(), currentOrg: response.organization };
|
|
|
|
|
} catch {
|
2026-03-20 16:43:44 +00:00
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const deleteOrganizationAction = organizationsStatePart.createAction<{
|
|
|
|
|
organizationId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_DeleteOrganization>(
|
|
|
|
|
'deleteOrganization',
|
|
|
|
|
);
|
|
|
|
|
await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
organizationId: dataArg.organizationId,
|
|
|
|
|
});
|
|
|
|
|
const listReq = createTypedRequest<interfaces.requests.IReq_GetOrganizations>(
|
|
|
|
|
'getOrganizations',
|
|
|
|
|
);
|
|
|
|
|
const listResp = await listReq.fire({ identity: context.identity });
|
|
|
|
|
return {
|
|
|
|
|
...statePartArg.getState(),
|
|
|
|
|
organizations: listResp.organizations,
|
|
|
|
|
currentOrg: null,
|
|
|
|
|
};
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const fetchRepositoriesAction = organizationsStatePart.createAction<{
|
|
|
|
|
organizationId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetRepositories>(
|
|
|
|
|
'getRepositories',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
organizationId: dataArg.organizationId,
|
|
|
|
|
});
|
|
|
|
|
return { ...statePartArg.getState(), repositories: response.repositories };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const fetchMembersAction = organizationsStatePart.createAction<{
|
|
|
|
|
organizationId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetOrganizationMembers>(
|
|
|
|
|
'getOrganizationMembers',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
organizationId: dataArg.organizationId,
|
|
|
|
|
});
|
|
|
|
|
return { ...statePartArg.getState(), members: response.members };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Package Actions
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
export const searchPackagesAction = packagesStatePart.createAction<{
|
|
|
|
|
query?: string;
|
|
|
|
|
protocol?: string;
|
|
|
|
|
offset?: number;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_SearchPackages>(
|
|
|
|
|
'searchPackages',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity || undefined,
|
|
|
|
|
query: dataArg.query,
|
|
|
|
|
protocol: dataArg.protocol as interfaces.data.TRegistryProtocol | undefined,
|
|
|
|
|
offset: dataArg.offset,
|
|
|
|
|
limit: 50,
|
|
|
|
|
});
|
|
|
|
|
return {
|
|
|
|
|
...statePartArg.getState(),
|
|
|
|
|
packages: response.packages,
|
|
|
|
|
total: response.total,
|
|
|
|
|
query: dataArg.query || '',
|
|
|
|
|
protocolFilter: dataArg.protocol || '',
|
|
|
|
|
};
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const fetchPackageAction = packagesStatePart.createAction<{
|
|
|
|
|
packageId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetPackage>('getPackage');
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity || undefined,
|
|
|
|
|
packageId: dataArg.packageId,
|
|
|
|
|
});
|
|
|
|
|
return { ...statePartArg.getState(), currentPackage: response.package };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const fetchPackageVersionsAction = packagesStatePart.createAction<{
|
|
|
|
|
packageId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetPackageVersions>(
|
|
|
|
|
'getPackageVersions',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity || undefined,
|
|
|
|
|
packageId: dataArg.packageId,
|
|
|
|
|
});
|
|
|
|
|
return { ...statePartArg.getState(), versions: response.versions };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const deletePackageAction = packagesStatePart.createAction<{
|
|
|
|
|
packageId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_DeletePackage>(
|
|
|
|
|
'deletePackage',
|
|
|
|
|
);
|
|
|
|
|
await typedRequest.fire({ identity: context.identity, packageId: dataArg.packageId });
|
|
|
|
|
return { ...statePartArg.getState(), currentPackage: null };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Token Actions
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
export const fetchTokensAction = tokensStatePart.createAction<{
|
|
|
|
|
organizationId?: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetTokens>('getTokens');
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
organizationId: dataArg?.organizationId,
|
|
|
|
|
});
|
|
|
|
|
return { tokens: response.tokens };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const createTokenAction = tokensStatePart.createAction<{
|
|
|
|
|
name: string;
|
|
|
|
|
protocols: interfaces.data.TRegistryProtocol[];
|
|
|
|
|
scopes: interfaces.data.ITokenScope[];
|
|
|
|
|
organizationId?: string;
|
|
|
|
|
expiresInDays?: number;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_CreateToken>('createToken');
|
|
|
|
|
await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
...dataArg,
|
|
|
|
|
});
|
|
|
|
|
// Re-fetch
|
|
|
|
|
const listReq = createTypedRequest<interfaces.requests.IReq_GetTokens>('getTokens');
|
|
|
|
|
const listResp = await listReq.fire({ identity: context.identity });
|
|
|
|
|
return { tokens: listResp.tokens };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const revokeTokenAction = tokensStatePart.createAction<{
|
|
|
|
|
tokenId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_RevokeToken>('revokeToken');
|
|
|
|
|
await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
tokenId: dataArg.tokenId,
|
|
|
|
|
});
|
|
|
|
|
const listReq = createTypedRequest<interfaces.requests.IReq_GetTokens>('getTokens');
|
|
|
|
|
const listResp = await listReq.fire({ identity: context.identity });
|
|
|
|
|
return { tokens: listResp.tokens };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Settings Actions
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
export const fetchUserSessionsAction = settingsStatePart.createAction(async (statePartArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetUserSessions>(
|
|
|
|
|
'getUserSessions',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({ identity: context.identity });
|
|
|
|
|
return { ...statePartArg.getState(), sessions: response.sessions };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const changePasswordAction = settingsStatePart.createAction<{
|
|
|
|
|
currentPassword: string;
|
|
|
|
|
newPassword: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_ChangePassword>(
|
|
|
|
|
'changePassword',
|
|
|
|
|
);
|
|
|
|
|
await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
currentPassword: dataArg.currentPassword,
|
|
|
|
|
newPassword: dataArg.newPassword,
|
|
|
|
|
});
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const updateProfileAction = settingsStatePart.createAction<{
|
|
|
|
|
displayName?: string;
|
|
|
|
|
avatarUrl?: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_UpdateUser>('updateUser');
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
userId: context.identity.userId,
|
|
|
|
|
...dataArg,
|
|
|
|
|
});
|
|
|
|
|
return { ...statePartArg.getState(), user: response.user };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const revokeSessionAction = settingsStatePart.createAction<{
|
|
|
|
|
sessionId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_RevokeSession>(
|
|
|
|
|
'revokeSession',
|
|
|
|
|
);
|
|
|
|
|
await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
sessionId: dataArg.sessionId,
|
|
|
|
|
});
|
|
|
|
|
// Re-fetch sessions
|
|
|
|
|
const listReq = createTypedRequest<interfaces.requests.IReq_GetUserSessions>('getUserSessions');
|
|
|
|
|
const listResp = await listReq.fire({ identity: context.identity });
|
|
|
|
|
return { ...statePartArg.getState(), sessions: listResp.sessions };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Admin Actions
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
export const fetchAdminProvidersAction = adminStatePart.createAction(async (statePartArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetAdminProviders>(
|
|
|
|
|
'getAdminProviders',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({ identity: context.identity });
|
|
|
|
|
return { ...statePartArg.getState(), providers: response.providers };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const fetchPlatformSettingsAction = adminStatePart.createAction(async (statePartArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_GetPlatformSettings>(
|
|
|
|
|
'getPlatformSettings',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({ identity: context.identity });
|
|
|
|
|
return { ...statePartArg.getState(), platformSettings: response.settings };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const updatePlatformSettingsAction = adminStatePart.createAction<{
|
|
|
|
|
auth?: Partial<interfaces.data.IPlatformAuthSettings>;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_UpdatePlatformSettings>(
|
|
|
|
|
'updatePlatformSettings',
|
|
|
|
|
);
|
|
|
|
|
const response = await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
auth: dataArg.auth,
|
|
|
|
|
});
|
|
|
|
|
return { ...statePartArg.getState(), platformSettings: response.settings };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const deleteAdminProviderAction = adminStatePart.createAction<{
|
|
|
|
|
providerId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_DeleteAdminProvider>(
|
|
|
|
|
'deleteAdminProvider',
|
|
|
|
|
);
|
|
|
|
|
await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
providerId: dataArg.providerId,
|
|
|
|
|
});
|
|
|
|
|
const listReq = createTypedRequest<interfaces.requests.IReq_GetAdminProviders>(
|
|
|
|
|
'getAdminProviders',
|
|
|
|
|
);
|
|
|
|
|
const listResp = await listReq.fire({ identity: context.identity });
|
|
|
|
|
return { ...statePartArg.getState(), providers: listResp.providers };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const testAdminProviderAction = adminStatePart.createAction<{
|
|
|
|
|
providerId: string;
|
|
|
|
|
}>(async (statePartArg, dataArg) => {
|
|
|
|
|
const context = getActionContext();
|
|
|
|
|
if (!context.identity) return statePartArg.getState();
|
|
|
|
|
try {
|
|
|
|
|
const typedRequest = createTypedRequest<interfaces.requests.IReq_TestAdminProvider>(
|
|
|
|
|
'testAdminProvider',
|
|
|
|
|
);
|
|
|
|
|
await typedRequest.fire({
|
|
|
|
|
identity: context.identity,
|
|
|
|
|
providerId: dataArg.providerId,
|
|
|
|
|
});
|
|
|
|
|
// Re-fetch to get updated test results
|
|
|
|
|
const listReq = createTypedRequest<interfaces.requests.IReq_GetAdminProviders>(
|
|
|
|
|
'getAdminProviders',
|
|
|
|
|
);
|
|
|
|
|
const listResp = await listReq.fire({ identity: context.identity });
|
|
|
|
|
return { ...statePartArg.getState(), providers: listResp.providers };
|
|
|
|
|
} catch {
|
|
|
|
|
return statePartArg.getState();
|
|
|
|
|
}
|
|
|
|
|
});
|