Client:OAuth: refactoring

This commit is contained in:
Timofey Boyko 2024-06-27 13:31:49 +03:00
parent 341110b486
commit def151fe66
22 changed files with 241 additions and 176 deletions

View File

@ -1,7 +1,7 @@
import {
IClientProps,
IClientReqDTO,
IScope,
TScope,
} from "@docspace/shared/utils/oauth/types";
import { SettingsStore } from "@docspace/shared/store/SettingsStore";
@ -41,7 +41,7 @@ export interface ClientFormProps {
id?: string;
client?: IClientProps;
scopeList?: IScope[];
scopeList?: TScope[];
fetchScopes?: () => Promise<void>;

View File

@ -2,8 +2,8 @@ import React from "react";
import {
IClientReqDTO,
IFilteredScopes,
IScope,
TFilteredScopes,
TScope,
} from "@docspace/shared/utils/oauth/types";
import {
filterScopeByGroup,
@ -22,8 +22,8 @@ import {
StyledScopesName,
} from "../ClientForm.styled";
interface IScopesBlockProps {
scopes: IScope[];
interface TScopesBlockProps {
scopes: TScope[];
selectedScopes: string[];
onAddScope: (name: keyof IClientReqDTO, scope: string) => void;
t: TTranslation;
@ -36,9 +36,9 @@ const ScopesBlock = ({
onAddScope,
t,
isEdit,
}: IScopesBlockProps) => {
}: TScopesBlockProps) => {
const [checkedScopes, setCheckedScopes] = React.useState<string[]>([]);
const [filteredScopes, setFilteredScopes] = React.useState<IFilteredScopes>(
const [filteredScopes, setFilteredScopes] = React.useState<TFilteredScopes>(
filterScopeByGroup(selectedScopes, scopes),
);

View File

@ -3,7 +3,7 @@ import { inject, observer } from "mobx-react";
import styled from "styled-components";
import { useTranslation } from "react-i18next";
import { IClientProps, IScope } from "@docspace/shared/utils/oauth/types";
import { IClientProps, TScope } from "@docspace/shared/utils/oauth/types";
import ScopeList from "@docspace/shared/utils/oauth/ScopeList";
import getCorrectDate from "@docspace/shared/utils/getCorrectDate";
import { getCookie } from "@docspace/shared/utils/cookie";
@ -124,7 +124,7 @@ StyledContainer.defaultProps = { theme: Base };
interface InfoDialogProps {
visible: boolean;
scopeList?: IScope[];
scopeList?: TScope[];
setInfoDialogVisible?: (value: boolean) => void;
getContextMenuItems?: (

View File

@ -1,4 +1,4 @@
import { IClientProps } from "@docspace/shared/utils/oauth/interfaces";
import { IClientProps } from "@docspace/shared/utils/oauth/types";
import { DeviceUnionType } from "SRC_DIR/Hooks/useViewEffect";
import { ViewAsType } from "SRC_DIR/store/OAuthStore";

View File

@ -27,7 +27,6 @@ export const OAuthRow = (props: RowProps) => {
return (
<Row
key={item.clientId}
// data={item}
contextOptions={contextOptions}
element={element}
mode="modern"
@ -35,6 +34,7 @@ export const OAuthRow = (props: RowProps) => {
inProgress={inProgress}
onSelect={() => setSelection && setSelection(item.clientId)}
onRowClick={() => {}}
className={`oauth2-row${isChecked ? " oauth2-row-selected" : ""}`}
>
<RowContent
sectionWidth={sectionWidth}

View File

@ -1,5 +1,3 @@
import React from "react";
import { Text } from "@docspace/shared/components/text";
import { Link, LinkTarget, LinkType } from "@docspace/shared/components/link";

View File

@ -2,6 +2,7 @@ import styled from "styled-components";
import { RowContainer } from "@docspace/shared/components/row-container";
import { RowContent } from "@docspace/shared/components/row-content";
import { tablet } from "@docspace/shared/utils/device";
export const StyledRowContainer = styled(RowContainer)`
margin-top: 0px;
@ -22,6 +23,51 @@ export const StyledRowContainer = styled(RowContainer)`
height: 32px;
max-height: 32px;
}
.oauth2-row-selected {
background: ${(props) =>
props.theme.filesSection.rowView.checkedBackground};
cursor: pointer;
border-bottom: none;
margin-left: -24px;
margin-right: -24px;
padding-left: 24px;
padding-right: 24px;
@media ${tablet} {
margin-left: -16px;
margin-right: -16px;
padding-left: 16px;
padding-right: 16px;
}
}
.oauth2-row {
margin-top: -3px;
padding-top: 3px;
:hover {
background: ${(props) =>
props.theme.filesSection.rowView.checkedBackground};
cursor: pointer;
border-bottom: none;
margin-left: -24px;
margin-right: -24px;
padding-left: 24px;
padding-right: 24px;
@media ${tablet} {
margin-left: -16px;
margin-right: -16px;
padding-left: 16px;
padding-right: 16px;
}
}
}
`;
export const StyledRowContent = styled(RowContent)`

View File

@ -1,4 +1,4 @@
import { IClientProps } from "@docspace/shared/utils/oauth/interfaces";
import { IClientProps } from "@docspace/shared/utils/oauth/types";
import { ContextMenuModel } from "@docspace/shared/components/context-menu";
import { TTranslation } from "@docspace/shared/types";
@ -17,7 +17,7 @@ export interface RowViewProps {
activeClients?: string[];
hasNextPage?: boolean;
itemCount?: number;
fetchNextClients?: (startIndex: number) => Promise<void>;
fetchNextConsents?: (startIndex: number) => Promise<void>;
changeClientStatus?: (clientId: string, status: boolean) => Promise<void>;
}

View File

@ -21,14 +21,14 @@ const RowView = (props: RowViewProps) => {
getContextMenuItems,
hasNextPage,
itemCount,
fetchNextClients,
fetchNextConsents,
} = props;
const fetchMoreFiles = React.useCallback(
async ({ startIndex }: { startIndex: number; stopIndex: number }) => {
await fetchNextClients?.(startIndex);
await fetchNextConsents?.(startIndex);
},
[fetchNextClients],
[fetchNextConsents],
);
return (
@ -66,9 +66,9 @@ export default inject(({ oauthStore }: { oauthStore: OAuthStoreProps }) => {
changeClientStatus,
getContextMenuItems,
activeClients,
hasNextPage,
itemCount,
fetchNextClients,
consentHasNextPage,
consentItemCount,
fetchNextConsents,
} = oauthStore;
return {
@ -79,8 +79,8 @@ export default inject(({ oauthStore }: { oauthStore: OAuthStoreProps }) => {
setSelection,
activeClients,
getContextMenuItems,
hasNextPage,
itemCount,
fetchNextClients,
hasNextPage: consentHasNextPage,
itemCount: consentItemCount,
fetchNextConsents,
};
})(observer(RowView));

View File

@ -23,11 +23,11 @@ const StyledTableRow = styled(TableRow)`
.table-container_cell {
text-overflow: ellipsis;
padding-right: 8px;
padding-inline-end: 8px;
}
.mr-8 {
margin-right: 8px;
margin-inline-end: 8px;
}
.textOverflow {
@ -46,7 +46,7 @@ const StyledTableRow = styled(TableRow)`
input {
position: relative;
margin-left: -8px;
margin-inline-start: -8px;
}
}

View File

@ -1,4 +1,4 @@
import { IClientProps } from "@docspace/shared/utils/oauth/interfaces";
import { IClientProps } from "@docspace/shared/utils/oauth/types";
import { ContextMenuModel } from "@docspace/shared/components/context-menu";
import { TTranslation } from "@docspace/shared/types";
@ -19,7 +19,7 @@ export interface TableViewProps {
activeClients?: string[];
hasNextPage?: boolean;
itemCount?: number;
fetchNextClients?: (startIndex: number) => Promise<void>;
fetchNextConsents?: (startIndex: number) => Promise<void>;
changeClientStatus?: (clientId: string, status: boolean) => Promise<void>;
}

View File

@ -1,5 +1,5 @@
import React from "react";
import styled from "styled-components";
import styled, { css } from "styled-components";
import { Text } from "@docspace/shared/components/text";
import { Checkbox } from "@docspace/shared/components/checkbox";
@ -8,11 +8,18 @@ import { Loader, LoaderTypes } from "@docspace/shared/components/loader";
const StyledContainer = styled.div`
.table-container_row-checkbox {
margin-left: -8px;
margin-inline-start: -8px;
width: 16px;
padding: 16px 8px 16px 16px;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
padding: 16px 16px 16px 8px;
`
: css`
padding: 16px 8px 16px 16px;
`}
}
`;
@ -53,7 +60,11 @@ const NameCell = ({
size="16px"
/>
) : (
<TableCell className="table-container_element-wrapper">
<TableCell
className="table-container_element-wrapper"
hasAccess
checked={isChecked}
>
<StyledContainer className="table-container_element-container">
<div className="table-container_element">
{icon && <StyledImage src={icon} alt="App icon" />}

View File

@ -26,7 +26,7 @@ const TableView = ({
userId,
hasNextPage,
itemCount,
fetchNextClients,
fetchNextConsents,
}: TableViewProps) => {
const tableRef = React.useRef<HTMLDivElement>(null);
@ -58,9 +58,9 @@ const TableView = ({
const fetchMoreFiles = React.useCallback(
async ({ startIndex }: { startIndex: number; stopIndex: number }) => {
await fetchNextClients?.(startIndex);
await fetchNextConsents?.(startIndex);
},
[fetchNextClients],
[fetchNextConsents],
);
return (
@ -115,9 +115,9 @@ export default inject(
changeClientStatus,
getContextMenuItems,
activeClients,
hasNextPage,
itemCount,
fetchNextClients,
consentHasNextPage,
consentItemCount,
fetchNextConsents,
} = oauthStore;
return {
@ -130,9 +130,9 @@ export default inject(
setBufferSelection,
activeClients,
getContextMenuItems,
hasNextPage,
itemCount,
fetchNextClients,
hasNextPage: consentHasNextPage,
itemCount: consentItemCount,
fetchNextConsents,
};
},
)(observer(TableView));

View File

@ -15,13 +15,13 @@ import {
IClientListProps,
IClientProps,
IClientReqDTO,
IScope,
TScope,
} from "@docspace/shared/utils/oauth/types";
import { toastr } from "@docspace/shared/components/toast";
import { AuthenticationMethod } from "@docspace/shared/enums";
import { TData } from "@docspace/shared/components/toast/Toast.type";
import { UserStore } from "@docspace/shared/store/UserStore";
import { TTranslation } from "@docspace/shared/types";
import { Nullable, TTranslation } from "@docspace/shared/types";
import EnableReactSvgUrl from "PUBLIC_DIR/images/enable.react.svg?url";
import RemoveReactSvgUrl from "PUBLIC_DIR/images/remove.react.svg?url";
@ -64,6 +64,9 @@ export interface OAuthStoreProps {
clientsIsLoading: boolean;
setClientsIsLoading: (value: boolean) => void;
consentsIsLoading: boolean;
setConsentsIsLoading: (value: boolean) => void;
clientSecret: string;
setClientSecret: (value: string) => void;
@ -75,7 +78,9 @@ export interface OAuthStoreProps {
fetchNextClients: (startIndex: number) => Promise<void>;
consents: IClientProps[];
fetchConsents: () => Promise<void>;
fetchNextConsents: (startIndex: number) => Promise<void>;
saveClient: (client: IClientReqDTO) => Promise<void>;
@ -89,12 +94,16 @@ export interface OAuthStoreProps {
revokeClient: (clientId: string[]) => Promise<void>;
userStore: UserStore | null;
userStore: Nullable<UserStore>;
currentPage: number;
nextPage: number | null;
nextPage: Nullable<number>;
itemCount: number;
consentCurrentPage: number;
consentNextPage: Nullable<number>;
consentItemCount: number;
selection: string[];
setSelection: (clientId: string) => void;
@ -104,7 +113,7 @@ export interface OAuthStoreProps {
activeClients: string[];
setActiveClient: (clientId: string) => void;
scopes: IScope[];
scopes: TScope[];
fetchScopes: () => Promise<void>;
getContextMenuItems: (
@ -117,20 +126,27 @@ export interface OAuthStoreProps {
clientList: IClientProps[];
isEmptyClientList: boolean;
hasNextPage: boolean;
scopeList: IScope[];
consentHasNextPage: boolean;
scopeList: TScope[];
}
class OAuthStore implements OAuthStoreProps {
userStore: UserStore | null = null;
userStore: Nullable<UserStore> = null;
viewAs: ViewAsType = "table";
currentPage: number = 0;
nextPage: number | null = null;
nextPage: Nullable<number> = null;
itemCount: number = 0;
consentCurrentPage: number = 0;
consentNextPage: Nullable<number> = null;
consentItemCount: number = 0;
infoDialogVisible: boolean = false;
previewDialogVisible: boolean = false;
@ -149,10 +165,12 @@ class OAuthStore implements OAuthStoreProps {
activeClients: string[] = [];
scopes: IScope[] = [];
scopes: TScope[] = [];
clientsIsLoading: boolean = true;
consentsIsLoading: boolean = true;
clientSecret: string = "";
consents: IClientProps[] = [];
@ -229,6 +247,10 @@ class OAuthStore implements OAuthStoreProps {
this.clientsIsLoading = value;
};
setConsentsIsLoading = (value: boolean) => {
this.consentsIsLoading = value;
};
setActiveClient = (clientId?: string) => {
if (!clientId) {
this.activeClients = [];
@ -254,15 +276,15 @@ class OAuthStore implements OAuthStoreProps {
const clientList: IClientListProps = await getClientList(0, PAGE_LIMIT);
runInAction(() => {
this.clients = [...clientList.content];
this.clients = [...clientList.data];
this.selection = [];
this.currentPage = clientList.page;
this.nextPage = clientList.next;
if (clientList.next) {
this.itemCount = clientList.content.length + 2;
this.itemCount = clientList.data.length + 2;
} else {
this.itemCount = clientList.content.length;
this.itemCount = clientList.data.length;
}
});
this.setClientsIsLoading(false);
@ -291,9 +313,9 @@ class OAuthStore implements OAuthStoreProps {
runInAction(() => {
this.currentPage = clientList.page;
this.nextPage = clientList.next || null;
this.clients = [...this.clients, ...clientList.content];
this.clients = [...this.clients, ...clientList.data];
this.itemCount += clientList.content.length;
this.itemCount += clientList.data.length;
});
this.setClientsIsLoading(false);
@ -301,17 +323,52 @@ class OAuthStore implements OAuthStoreProps {
fetchConsents = async () => {
try {
const consentList: IClientProps[] = await getConsentList();
this.setClientsIsLoading(true);
const consentList = await getConsentList(0, PAGE_LIMIT);
runInAction(() => {
this.consents = [...consentList];
this.consents = [...consentList.consents];
this.selection = [];
this.consentCurrentPage = consentList.page;
this.consentNextPage = consentList.next;
if (consentList.next) {
this.consentItemCount = consentList.data.length + 2;
} else {
this.consentItemCount = consentList.data.length;
}
});
this.setClientsIsLoading(false);
} catch (e) {
const err = e as TData;
toastr.error(err);
}
};
fetchNextConsents = async (startIndex: number) => {
if (this.consentsIsLoading) return;
this.setConsentsIsLoading(true);
const page = startIndex / PAGE_LIMIT;
runInAction(() => {
this.consentCurrentPage = page + 1;
});
const consentList = await getConsentList(this.nextPage || page, PAGE_LIMIT);
runInAction(() => {
this.currentPage = consentList.page;
this.nextPage = consentList.next || null;
this.consents = [...this.consents, ...consentList.consents];
this.consentItemCount += consentList.data.length;
});
this.setConsentsIsLoading(false);
};
saveClient = async (client: IClientReqDTO) => {
try {
const newClient = await addClient(client);
@ -671,6 +728,10 @@ class OAuthStore implements OAuthStoreProps {
return !!this.nextPage;
}
get consentHasNextPage() {
return !!this.consentNextPage;
}
get scopeList() {
return this.scopes;
}

View File

@ -24,8 +24,6 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import { INoAuthClientProps } from "@docspace/shared/utils/oauth/types";
import { getOAuthClient, getSettings } from "@/utils/actions";
import Login from "@/components/Login";
import LoginForm from "@/components/LoginForm";

View File

@ -41,7 +41,7 @@ import {
AvatarSize,
} from "@docspace/shared/components/avatar";
import { deleteCookie } from "@docspace/shared/utils/cookie";
import { IClientProps, IScope } from "@docspace/shared/utils/oauth/types";
import { IClientProps, TScope } from "@docspace/shared/utils/oauth/types";
import { TUser } from "@docspace/shared/api/people/types";
import api from "@docspace/shared/api";
@ -88,7 +88,7 @@ const StyledUserContainer = styled.div`
interface IConsentProps {
client: IClientProps;
scopes: IScope[];
scopes: TScope[];
user: TUser;
}

View File

@ -42,7 +42,7 @@ import {
TThirdPartyProvider,
TVersionBuild,
} from "@docspace/shared/api/settings/types";
import { IScope } from "@docspace/shared/utils/oauth/types";
import { TScope } from "@docspace/shared/utils/oauth/types";
import { transformToClientProps } from "@docspace/shared/utils/oauth";
export const checkIsAuthenticated = async () => {
@ -176,7 +176,7 @@ export async function getScopeList() {
const scopes = await scopeList.json();
return scopes as IScope[];
return scopes as TScope[];
}
export async function getOAuthClient(clientId: string) {

View File

@ -1,5 +1,5 @@
{
"date": "2024626_163846",
"date": "2024627_121634",
"checksums": {
"api.js": "0efbae3383bf6c6b6f26d573eee164d2",
"api.poly.js": "2a2ac2c0e4a7007b61d2d1ff7b00a22e",

View File

@ -7,9 +7,10 @@ import {
IClientResDTO,
IClientListProps,
IClientListDTO,
IScope,
TScope,
IClientReqDTO,
IGetConsentList,
TConsentData,
TConsentList,
} from "../../utils/oauth/types";
export const getClient = async (clientId: string): Promise<IClientProps> => {
@ -30,12 +31,12 @@ export const getClientList = async (
url: `/clients?page=${page}&limit=${limit}`,
})) as IClientListDTO;
const clients: IClientListProps = { ...data, content: [] };
const clients: IClientListProps = { ...data, data: [] };
data.data.forEach((item) => {
const client = transformToClientProps(item);
clients.content.push({ ...client });
clients.data.push({ ...client });
});
return clients;
@ -90,45 +91,50 @@ export const deleteClient = async (clientId: string): Promise<void> => {
});
};
export const getScope = async (name: string): Promise<IScope> => {
export const getScope = async (name: string): Promise<TScope> => {
const scope = (await request({
method: "get",
url: `/scopes/${name}`,
})) as IScope;
})) as TScope;
return scope;
};
export const getScopeList = async (): Promise<IScope[]> => {
export const getScopeList = async (): Promise<TScope[]> => {
const scopeList = (await request({
method: "get",
url: `/scopes`,
})) as IScope[];
})) as TScope[];
return scopeList;
};
export const getConsentList = async (): Promise<IClientProps[]> => {
const clients = (await request({
export const getConsentList = async (
page: number = 0,
limit: number = 100,
): Promise<TConsentList & { consents: IClientProps[] }> => {
const consentList = (await request({
method: "get",
url: "/clients/consents",
})) as IGetConsentList[];
url: `/clients/consents?page=${page}&limit=${limit}`,
})) as TConsentList;
const consents: IClientProps[] = [];
clients.forEach(({ client, invalidated, modified_at }: IGetConsentList) => {
const consentClient: IClientResDTO = {
...client,
client_secret: "",
logout_redirect_uri: "",
};
consentList.data.forEach(
({ client, invalidated, modified_at }: TConsentData) => {
const consentClient: IClientResDTO = {
...client,
client_secret: "",
logout_redirect_uri: "",
};
const cl = transformToClientProps(consentClient);
const cl = transformToClientProps(consentClient);
if (!invalidated) consents.push({ ...cl, modifiedOn: modified_at });
});
if (!invalidated) consents.push({ ...cl, modifiedOn: modified_at });
},
);
return consents;
return { ...consentList, consents };
};
export const revokeUserClient = async (clientId: string): Promise<void> => {
@ -138,23 +144,6 @@ export const revokeUserClient = async (clientId: string): Promise<void> => {
});
};
export const onOAuthLogin = (clientId: string) => {
const formData = new FormData();
formData.set("username", clientId);
formData.set("password", clientId);
return request({
method: "post",
url: `/oauth2/login?client_id=${clientId}`,
data: formData,
withRedirect: true,
headers: {
"X-Disable-Redirect": "true",
},
});
};
export const onOAuthSubmit = (
clientId: string,
clientState: string,
@ -165,8 +154,6 @@ export const onOAuthSubmit = (
formData.append("client_id", clientId);
formData.append("state", clientState);
// return;
scope.forEach((s) => {
formData.append("scope", s);
});
@ -176,9 +163,6 @@ export const onOAuthSubmit = (
url: `/oauth2/authorize`,
data: formData,
withRedirect: true,
headers: {
"X-Disable-Redirect": "true",
},
});
};
@ -193,8 +177,5 @@ export const onOAuthCancel = (clientId: string, clientState: string) => {
url: `/oauth2/authorize`,
data: formData,
withRedirect: true,
headers: {
"X-Disable-Redirect": "true",
},
});
};

View File

@ -5,7 +5,7 @@ import { Base } from "../../themes";
import { ScopeType } from "../../enums";
import { TTranslation } from "../../types";
import { IFilteredScopes, IScope } from "./types";
import { TFilteredScopes, TScope } from "./types";
import { filterScopeByGroup } from ".";
const StyledScopeList = styled.div`
@ -42,20 +42,20 @@ const StyledScopeItem = styled.div`
StyledScopeItem.defaultProps = { theme: Base };
interface IScopeListProps {
interface TScopeListProps {
selectedScopes: string[];
scopes: IScope[];
scopes: TScope[];
t: TTranslation;
}
const ScopeList = ({ selectedScopes, scopes, t }: IScopeListProps) => {
const ScopeList = ({ selectedScopes, scopes, t }: TScopeListProps) => {
const [renderedScopes, setRenderedScopes] = React.useState<string[]>([]);
React.useEffect(() => {
const result: string[] = [];
const filteredScopes: IFilteredScopes = filterScopeByGroup(
const filteredScopes: TFilteredScopes = filterScopeByGroup(
selectedScopes,
scopes,
);

View File

@ -7,8 +7,8 @@ import {
IClientResDTO,
IClientReqDTO,
IClientProps,
IScope,
IFilteredScopes,
TScope,
TFilteredScopes,
} from "./types";
export const transformToClientProps = (
@ -122,17 +122,17 @@ export const getScopeTKeyName = (group: ScopeGroup) => {
export const filterScopeByGroup = (
checkedScopes: string[],
scopes: IScope[],
scopes: TScope[],
) => {
const filteredScopes: IFilteredScopes = {};
const filteredScopes: TFilteredScopes = {};
scopes.forEach((scope) => {
const isChecked = checkedScopes.includes(scope.name);
const isRead = ScopeType.read === scope.type;
const tKey = getScopeTKeyDescription(scope.group, scope.type);
const read = isRead ? { ...scope, tKey } : ({} as IScope);
const write = !isRead ? { ...scope, tKey } : ({} as IScope);
const read = isRead ? { ...scope, tKey } : ({} as TScope);
const write = !isRead ? { ...scope, tKey } : ({} as TScope);
if (scope.group === ScopeGroup.openid) {
filteredScopes[scope.group] = {

View File

@ -1,49 +1,21 @@
import { Nullable } from "../../types";
import { AuthenticationMethod, ScopeGroup, ScopeType } from "../../enums";
export interface IScope {
export type TScope = {
name: string;
group: ScopeGroup;
type: ScopeType;
tKey?: string;
}
};
export interface IFilteredScopes {
export type TFilteredScopes = {
[key: string]: {
isChecked: boolean;
checkedType?: ScopeType;
read: IScope;
write?: IScope;
read: TScope;
write?: TScope;
};
}
export interface INoAuthClientProps {
name: string;
logo: string;
websiteUrl: string;
policyUrl?: string;
termsUrl?: string;
scopes?: string[];
clientId?: undefined;
clientSecret?: undefined;
description?: undefined;
authenticationMethods?: undefined;
tenant?: undefined;
redirectUris?: undefined;
logoutRedirectUri?: undefined;
enabled?: undefined;
invalidated?: undefined;
allowedOrigins?: undefined;
createdOn?: undefined;
modifiedOn?: undefined;
createdBy?: undefined;
modifiedBy?: undefined;
creatorAvatar?: undefined;
creatorDisplayName?: undefined;
}
};
export interface IClientProps {
name: string;
@ -124,22 +96,6 @@ export interface IClientResDTO {
website_url: string;
}
export interface IClientListProps {
content: IClientProps[];
page: number;
limit: number;
next: Nullable<number>;
previous: Nullable<number>;
}
export interface IClientListDTO {
data: IClientResDTO[];
page: number;
limit: number;
next: Nullable<number>;
previous: Nullable<number>;
}
export interface ISubmitReqDTO {
client_id: string;
state: string;
@ -171,7 +127,7 @@ export type TConsentClient = {
is_public: boolean;
};
export interface IGetConsentList {
export type TConsentData = {
client: TConsentClient;
invalidated: boolean;
modified_at: Date;
@ -179,4 +135,18 @@ export interface IGetConsentList {
registered_client_id: string;
scopes: string;
is_public: boolean;
}
};
type List<T> = {
data: T[];
page: number;
limit: number;
next: Nullable<number>;
previous: Nullable<number>;
};
export type IClientListProps = List<IClientProps>;
export type IClientListDTO = List<IClientResDTO>;
export type TConsentList = List<TConsentData>;