Feature/setup api versioning (#783)
* Setup API versioning * Update changelog
This commit is contained in:
parent
eb77652d6a
commit
6762572658
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Added API versioning
|
||||||
- Added more durations in the coupon system
|
- Added more durations in the coupon system
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Logger, ValidationPipe } from '@nestjs/common';
|
import { Logger, ValidationPipe, VersioningType } from '@nestjs/common';
|
||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
import { AppModule } from './app/app.module';
|
||||||
@ -7,8 +7,11 @@ import { environment } from './environments/environment';
|
|||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
app.enableCors();
|
app.enableCors();
|
||||||
const globalPrefix = 'api';
|
app.enableVersioning({
|
||||||
app.setGlobalPrefix(globalPrefix);
|
defaultVersion: '1',
|
||||||
|
type: VersioningType.URI
|
||||||
|
});
|
||||||
|
app.setGlobalPrefix('api');
|
||||||
app.useGlobalPipes(
|
app.useGlobalPipes(
|
||||||
new ValidationPipe({
|
new ValidationPipe({
|
||||||
forbidNonWhitelisted: true,
|
forbidNonWhitelisted: true,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<ng-container *ngIf="data.hasPermissionToUseSocialLogin">
|
<ng-container *ngIf="data.hasPermissionToUseSocialLogin">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<a color="accent" href="/api/auth/google" mat-flat-button
|
<a color="accent" href="/api/v1/auth/google" mat-flat-button
|
||||||
><ion-icon class="mr-1" name="logo-google"></ion-icon
|
><ion-icon class="mr-1" name="logo-google"></ion-icon
|
||||||
><span i18n>Sign in with Google</span></a
|
><span i18n>Sign in with Google</span></a
|
||||||
>
|
>
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
>
|
>
|
||||||
or
|
or
|
||||||
</div>
|
</div>
|
||||||
<a color="accent" href="/api/auth/google" mat-flat-button
|
<a color="accent" href="/api/v1/auth/google" mat-flat-button
|
||||||
><ion-icon class="mr-1" name="logo-google"></ion-icon
|
><ion-icon class="mr-1" name="logo-google"></ion-icon
|
||||||
><span i18n>Continue with Google</span></a
|
><span i18n>Continue with Google</span></a
|
||||||
>
|
>
|
||||||
|
@ -19,7 +19,7 @@ export class AdminService {
|
|||||||
|
|
||||||
public deleteProfileData({ dataSource, symbol }: UniqueAsset) {
|
public deleteProfileData({ dataSource, symbol }: UniqueAsset) {
|
||||||
return this.http.delete<void>(
|
return this.http.delete<void>(
|
||||||
`/api/admin/profile-data/${dataSource}/${symbol}`
|
`/api/v1/admin/profile-data/${dataSource}/${symbol}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ export class AdminService {
|
|||||||
symbol: string;
|
symbol: string;
|
||||||
}): Observable<AdminMarketDataDetails> {
|
}): Observable<AdminMarketDataDetails> {
|
||||||
return this.http
|
return this.http
|
||||||
.get<any>(`/api/admin/market-data/${dataSource}/${symbol}`)
|
.get<any>(`/api/v1/admin/market-data/${dataSource}/${symbol}`)
|
||||||
.pipe(
|
.pipe(
|
||||||
map((data) => {
|
map((data) => {
|
||||||
for (const item of data.marketData) {
|
for (const item of data.marketData) {
|
||||||
@ -43,16 +43,16 @@ export class AdminService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public gatherMax() {
|
public gatherMax() {
|
||||||
return this.http.post<void>(`/api/admin/gather/max`, {});
|
return this.http.post<void>(`/api/v1/admin/gather/max`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
public gatherProfileData() {
|
public gatherProfileData() {
|
||||||
return this.http.post<void>(`/api/admin/gather/profile-data`, {});
|
return this.http.post<void>(`/api/v1/admin/gather/profile-data`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
public gatherProfileDataBySymbol({ dataSource, symbol }: UniqueAsset) {
|
public gatherProfileDataBySymbol({ dataSource, symbol }: UniqueAsset) {
|
||||||
return this.http.post<void>(
|
return this.http.post<void>(
|
||||||
`/api/admin/gather/profile-data/${dataSource}/${symbol}`,
|
`/api/v1/admin/gather/profile-data/${dataSource}/${symbol}`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ export class AdminService {
|
|||||||
}: UniqueAsset & {
|
}: UniqueAsset & {
|
||||||
date?: Date;
|
date?: Date;
|
||||||
}) {
|
}) {
|
||||||
let url = `/api/admin/gather/${dataSource}/${symbol}`;
|
let url = `/api/v1/admin/gather/${dataSource}/${symbol}`;
|
||||||
|
|
||||||
if (date) {
|
if (date) {
|
||||||
url = `${url}/${format(date, DATE_FORMAT)}`;
|
url = `${url}/${format(date, DATE_FORMAT)}`;
|
||||||
@ -82,7 +82,7 @@ export class AdminService {
|
|||||||
date: Date;
|
date: Date;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
}) {
|
}) {
|
||||||
const url = `/api/symbol/${dataSource}/${symbol}/${format(
|
const url = `/api/v1/symbol/${dataSource}/${symbol}/${format(
|
||||||
date,
|
date,
|
||||||
DATE_FORMAT
|
DATE_FORMAT
|
||||||
)}`;
|
)}`;
|
||||||
@ -101,7 +101,7 @@ export class AdminService {
|
|||||||
marketData: UpdateMarketDataDto;
|
marketData: UpdateMarketDataDto;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
}) {
|
}) {
|
||||||
const url = `/api/admin/market-data/${dataSource}/${symbol}/${format(
|
const url = `/api/v1/admin/market-data/${dataSource}/${symbol}/${format(
|
||||||
date,
|
date,
|
||||||
DATE_FORMAT
|
DATE_FORMAT
|
||||||
)}`;
|
)}`;
|
||||||
|
@ -8,6 +8,6 @@ export class CacheService {
|
|||||||
public constructor(private http: HttpClient) {}
|
public constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
public flush() {
|
public flush() {
|
||||||
return this.http.post<any>(`/api/cache/flush`, {});
|
return this.http.post<any>(`/api/v1/cache/flush`, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,10 @@ import {
|
|||||||
PortfolioChart,
|
PortfolioChart,
|
||||||
PortfolioDetails,
|
PortfolioDetails,
|
||||||
PortfolioInvestments,
|
PortfolioInvestments,
|
||||||
PortfolioPerformance,
|
|
||||||
PortfolioPerformanceResponse,
|
PortfolioPerformanceResponse,
|
||||||
PortfolioPublicDetails,
|
PortfolioPublicDetails,
|
||||||
PortfolioReport,
|
PortfolioReport,
|
||||||
PortfolioSummary,
|
PortfolioSummary,
|
||||||
UniqueAsset,
|
|
||||||
User
|
User
|
||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { permissions } from '@ghostfolio/common/permissions';
|
import { permissions } from '@ghostfolio/common/permissions';
|
||||||
@ -52,46 +50,46 @@ export class DataService {
|
|||||||
couponId?: string;
|
couponId?: string;
|
||||||
priceId: string;
|
priceId: string;
|
||||||
}) {
|
}) {
|
||||||
return this.http.post('/api/subscription/stripe/checkout-session', {
|
return this.http.post('/api/v1/subscription/stripe/checkout-session', {
|
||||||
couponId,
|
couponId,
|
||||||
priceId
|
priceId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchAccounts() {
|
public fetchAccounts() {
|
||||||
return this.http.get<Accounts>('/api/account');
|
return this.http.get<Accounts>('/api/v1/account');
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchAdminData() {
|
public fetchAdminData() {
|
||||||
return this.http.get<AdminData>('/api/admin');
|
return this.http.get<AdminData>('/api/v1/admin');
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchAdminMarketData() {
|
public fetchAdminMarketData() {
|
||||||
return this.http.get<AdminMarketData>('/api/admin/market-data');
|
return this.http.get<AdminMarketData>('/api/v1/admin/market-data');
|
||||||
}
|
}
|
||||||
|
|
||||||
public deleteAccess(aId: string) {
|
public deleteAccess(aId: string) {
|
||||||
return this.http.delete<any>(`/api/access/${aId}`);
|
return this.http.delete<any>(`/api/v1/access/${aId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public deleteAccount(aId: string) {
|
public deleteAccount(aId: string) {
|
||||||
return this.http.delete<any>(`/api/account/${aId}`);
|
return this.http.delete<any>(`/api/v1/account/${aId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public deleteOrder(aId: string) {
|
public deleteOrder(aId: string) {
|
||||||
return this.http.delete<any>(`/api/order/${aId}`);
|
return this.http.delete<any>(`/api/v1/order/${aId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public deleteUser(aId: string) {
|
public deleteUser(aId: string) {
|
||||||
return this.http.delete<any>(`/api/user/${aId}`);
|
return this.http.delete<any>(`/api/v1/user/${aId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchAccesses() {
|
public fetchAccesses() {
|
||||||
return this.http.get<Access[]>('/api/access');
|
return this.http.get<Access[]>('/api/v1/access');
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchChart({ range }: { range: DateRange }) {
|
public fetchChart({ range }: { range: DateRange }) {
|
||||||
return this.http.get<PortfolioChart>('/api/portfolio/chart', {
|
return this.http.get<PortfolioChart>('/api/v1/portfolio/chart', {
|
||||||
params: { range }
|
params: { range }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -103,7 +101,7 @@ export class DataService {
|
|||||||
params = params.append('activityIds', activityIds.join(','));
|
params = params.append('activityIds', activityIds.join(','));
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.http.get<Export>('/api/export', {
|
return this.http.get<Export>('/api/v1/export', {
|
||||||
params
|
params
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -121,7 +119,7 @@ export class DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fetchInvestments(): Observable<PortfolioInvestments> {
|
public fetchInvestments(): Observable<PortfolioInvestments> {
|
||||||
return this.http.get<any>('/api/portfolio/investments').pipe(
|
return this.http.get<any>('/api/v1/portfolio/investments').pipe(
|
||||||
map((response) => {
|
map((response) => {
|
||||||
if (response.firstOrderDate) {
|
if (response.firstOrderDate) {
|
||||||
response.firstOrderDate = parseISO(response.firstOrderDate);
|
response.firstOrderDate = parseISO(response.firstOrderDate);
|
||||||
@ -147,7 +145,7 @@ export class DataService {
|
|||||||
params = params.append('includeHistoricalData', includeHistoricalData);
|
params = params.append('includeHistoricalData', includeHistoricalData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.http.get<SymbolItem>(`/api/symbol/${dataSource}/${symbol}`, {
|
return this.http.get<SymbolItem>(`/api/v1/symbol/${dataSource}/${symbol}`, {
|
||||||
params
|
params
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -157,14 +155,14 @@ export class DataService {
|
|||||||
}: {
|
}: {
|
||||||
range: DateRange;
|
range: DateRange;
|
||||||
}): Observable<PortfolioPositions> {
|
}): Observable<PortfolioPositions> {
|
||||||
return this.http.get<PortfolioPositions>('/api/portfolio/positions', {
|
return this.http.get<PortfolioPositions>('/api/v1/portfolio/positions', {
|
||||||
params: { range }
|
params: { range }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchSymbols(aQuery: string) {
|
public fetchSymbols(aQuery: string) {
|
||||||
return this.http
|
return this.http
|
||||||
.get<{ items: LookupItem[] }>(`/api/symbol/lookup?query=${aQuery}`)
|
.get<{ items: LookupItem[] }>(`/api/v1/symbol/lookup?query=${aQuery}`)
|
||||||
.pipe(
|
.pipe(
|
||||||
map((respose) => {
|
map((respose) => {
|
||||||
return respose.items;
|
return respose.items;
|
||||||
@ -173,7 +171,7 @@ export class DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fetchOrders(): Observable<Activities> {
|
public fetchOrders(): Observable<Activities> {
|
||||||
return this.http.get<any>('/api/order').pipe(
|
return this.http.get<any>('/api/v1/order').pipe(
|
||||||
map(({ activities }) => {
|
map(({ activities }) => {
|
||||||
for (const activity of activities) {
|
for (const activity of activities) {
|
||||||
activity.createdAt = parseISO(activity.createdAt);
|
activity.createdAt = parseISO(activity.createdAt);
|
||||||
@ -185,14 +183,14 @@ export class DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fetchPortfolioDetails(aParams: { [param: string]: any }) {
|
public fetchPortfolioDetails(aParams: { [param: string]: any }) {
|
||||||
return this.http.get<PortfolioDetails>('/api/portfolio/details', {
|
return this.http.get<PortfolioDetails>('/api/v1/portfolio/details', {
|
||||||
params: aParams
|
params: aParams
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchPortfolioPerformance(params: { [param: string]: any }) {
|
public fetchPortfolioPerformance(params: { [param: string]: any }) {
|
||||||
return this.http.get<PortfolioPerformanceResponse>(
|
return this.http.get<PortfolioPerformanceResponse>(
|
||||||
'/api/portfolio/performance',
|
'/api/v1/portfolio/performance',
|
||||||
{
|
{
|
||||||
params
|
params
|
||||||
}
|
}
|
||||||
@ -201,16 +199,16 @@ export class DataService {
|
|||||||
|
|
||||||
public fetchPortfolioPublic(aId: string) {
|
public fetchPortfolioPublic(aId: string) {
|
||||||
return this.http.get<PortfolioPublicDetails>(
|
return this.http.get<PortfolioPublicDetails>(
|
||||||
`/api/portfolio/public/${aId}`
|
`/api/v1/portfolio/public/${aId}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchPortfolioReport() {
|
public fetchPortfolioReport() {
|
||||||
return this.http.get<PortfolioReport>('/api/portfolio/report');
|
return this.http.get<PortfolioReport>('/api/v1/portfolio/report');
|
||||||
}
|
}
|
||||||
|
|
||||||
public fetchPortfolioSummary(): Observable<PortfolioSummary> {
|
public fetchPortfolioSummary(): Observable<PortfolioSummary> {
|
||||||
return this.http.get<any>('/api/portfolio/summary').pipe(
|
return this.http.get<any>('/api/v1/portfolio/summary').pipe(
|
||||||
map((summary) => {
|
map((summary) => {
|
||||||
if (summary.firstOrderDate) {
|
if (summary.firstOrderDate) {
|
||||||
summary.firstOrderDate = parseISO(summary.firstOrderDate);
|
summary.firstOrderDate = parseISO(summary.firstOrderDate);
|
||||||
@ -229,7 +227,7 @@ export class DataService {
|
|||||||
symbol: string;
|
symbol: string;
|
||||||
}) {
|
}) {
|
||||||
return this.http
|
return this.http
|
||||||
.get<any>(`/api/portfolio/position/${dataSource}/${symbol}`)
|
.get<any>(`/api/v1/portfolio/position/${dataSource}/${symbol}`)
|
||||||
.pipe(
|
.pipe(
|
||||||
map((data) => {
|
map((data) => {
|
||||||
if (data.orders) {
|
if (data.orders) {
|
||||||
@ -245,47 +243,47 @@ export class DataService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public loginAnonymous(accessToken: string) {
|
public loginAnonymous(accessToken: string) {
|
||||||
return this.http.get<any>(`/api/auth/anonymous/${accessToken}`);
|
return this.http.get<any>(`/api/v1/auth/anonymous/${accessToken}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public postAccess(aAccess: CreateAccessDto) {
|
public postAccess(aAccess: CreateAccessDto) {
|
||||||
return this.http.post<OrderModel>(`/api/access`, aAccess);
|
return this.http.post<OrderModel>(`/api/v1/access`, aAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
public postAccount(aAccount: CreateAccountDto) {
|
public postAccount(aAccount: CreateAccountDto) {
|
||||||
return this.http.post<OrderModel>(`/api/account`, aAccount);
|
return this.http.post<OrderModel>(`/api/v1/account`, aAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public postOrder(aOrder: CreateOrderDto) {
|
public postOrder(aOrder: CreateOrderDto) {
|
||||||
return this.http.post<OrderModel>(`/api/order`, aOrder);
|
return this.http.post<OrderModel>(`/api/v1/order`, aOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public postUser() {
|
public postUser() {
|
||||||
return this.http.post<UserItem>(`/api/user`, {});
|
return this.http.post<UserItem>(`/api/v1/user`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
public putAccount(aAccount: UpdateAccountDto) {
|
public putAccount(aAccount: UpdateAccountDto) {
|
||||||
return this.http.put<UserItem>(`/api/account/${aAccount.id}`, aAccount);
|
return this.http.put<UserItem>(`/api/v1/account/${aAccount.id}`, aAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public putAdminSetting(key: string, aData: PropertyDto) {
|
public putAdminSetting(key: string, aData: PropertyDto) {
|
||||||
return this.http.put<void>(`/api/admin/settings/${key}`, aData);
|
return this.http.put<void>(`/api/v1/admin/settings/${key}`, aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public putOrder(aOrder: UpdateOrderDto) {
|
public putOrder(aOrder: UpdateOrderDto) {
|
||||||
return this.http.put<UserItem>(`/api/order/${aOrder.id}`, aOrder);
|
return this.http.put<UserItem>(`/api/v1/order/${aOrder.id}`, aOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public putUserSetting(aData: UpdateUserSettingDto) {
|
public putUserSetting(aData: UpdateUserSettingDto) {
|
||||||
return this.http.put<User>(`/api/user/setting`, aData);
|
return this.http.put<User>(`/api/v1/user/setting`, aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public putUserSettings(aData: UpdateUserSettingsDto) {
|
public putUserSettings(aData: UpdateUserSettingsDto) {
|
||||||
return this.http.put<User>(`/api/user/settings`, aData);
|
return this.http.put<User>(`/api/v1/user/settings`, aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public redeemCoupon(couponCode: string) {
|
public redeemCoupon(couponCode: string) {
|
||||||
return this.http.post('/api/subscription/redeem-coupon', {
|
return this.http.post('/api/v1/subscription/redeem-coupon', {
|
||||||
couponCode
|
couponCode
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -282,6 +282,6 @@ export class ImportTransactionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private postImport(aImportData: { orders: CreateOrderDto[] }) {
|
private postImport(aImportData: { orders: CreateOrderDto[] }) {
|
||||||
return this.http.post<void>('/api/import', aImportData);
|
return this.http.post<void>('/api/v1/import', aImportData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ export class UserService extends ObservableStore<UserStoreState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fetchUser() {
|
private fetchUser() {
|
||||||
return this.http.get<User>('/api/user').pipe(
|
return this.http.get<User>('/api/v1/user').pipe(
|
||||||
map((user) => {
|
map((user) => {
|
||||||
this.setState({ user }, UserStoreActions.GetUser);
|
this.setState({ user }, UserStoreActions.GetUser);
|
||||||
return user;
|
return user;
|
||||||
|
@ -35,7 +35,7 @@ export class WebAuthnService {
|
|||||||
public register() {
|
public register() {
|
||||||
return this.http
|
return this.http
|
||||||
.get<PublicKeyCredentialCreationOptionsJSON>(
|
.get<PublicKeyCredentialCreationOptionsJSON>(
|
||||||
`/api/auth/webauthn/generate-registration-options`,
|
`/api/v1/auth/webauthn/generate-registration-options`,
|
||||||
{}
|
{}
|
||||||
)
|
)
|
||||||
.pipe(
|
.pipe(
|
||||||
@ -48,7 +48,7 @@ export class WebAuthnService {
|
|||||||
}),
|
}),
|
||||||
switchMap((attResp) => {
|
switchMap((attResp) => {
|
||||||
return this.http.post<AuthDeviceDto>(
|
return this.http.post<AuthDeviceDto>(
|
||||||
`/api/auth/webauthn/verify-attestation`,
|
`/api/v1/auth/webauthn/verify-attestation`,
|
||||||
{
|
{
|
||||||
credential: attResp
|
credential: attResp
|
||||||
}
|
}
|
||||||
@ -65,31 +65,33 @@ export class WebAuthnService {
|
|||||||
|
|
||||||
public deregister() {
|
public deregister() {
|
||||||
const deviceId = this.getDeviceId();
|
const deviceId = this.getDeviceId();
|
||||||
return this.http.delete<AuthDeviceDto>(`/api/auth-device/${deviceId}`).pipe(
|
return this.http
|
||||||
catchError((error) => {
|
.delete<AuthDeviceDto>(`/api/v1/auth-device/${deviceId}`)
|
||||||
console.warn(`Could not deregister device ${deviceId}`, error);
|
.pipe(
|
||||||
return of(null);
|
catchError((error) => {
|
||||||
}),
|
console.warn(`Could not deregister device ${deviceId}`, error);
|
||||||
tap(() =>
|
return of(null);
|
||||||
this.settingsStorageService.removeSetting(
|
}),
|
||||||
WebAuthnService.WEB_AUTH_N_DEVICE_ID
|
tap(() =>
|
||||||
|
this.settingsStorageService.removeSetting(
|
||||||
|
WebAuthnService.WEB_AUTH_N_DEVICE_ID
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public login() {
|
public login() {
|
||||||
const deviceId = this.getDeviceId();
|
const deviceId = this.getDeviceId();
|
||||||
return this.http
|
return this.http
|
||||||
.post<PublicKeyCredentialRequestOptionsJSON>(
|
.post<PublicKeyCredentialRequestOptionsJSON>(
|
||||||
`/api/auth/webauthn/generate-assertion-options`,
|
`/api/v1/auth/webauthn/generate-assertion-options`,
|
||||||
{ deviceId }
|
{ deviceId }
|
||||||
)
|
)
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(startAuthentication),
|
switchMap(startAuthentication),
|
||||||
switchMap((assertionResponse) => {
|
switchMap((assertionResponse) => {
|
||||||
return this.http.post<{ authToken: string }>(
|
return this.http.post<{ authToken: string }>(
|
||||||
`/api/auth/webauthn/verify-assertion`,
|
`/api/v1/auth/webauthn/verify-assertion`,
|
||||||
{
|
{
|
||||||
credential: assertionResponse,
|
credential: assertionResponse,
|
||||||
deviceId
|
deviceId
|
||||||
|
@ -8,7 +8,7 @@ import { AppModule } from './app/app.module';
|
|||||||
import { environment } from './environments/environment';
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const response = await fetch('/api/info');
|
const response = await fetch('/api/v1/info');
|
||||||
const info: InfoItem = await response.json();
|
const info: InfoItem = await response.json();
|
||||||
|
|
||||||
if (window.localStorage.getItem('utm_source') === 'trusted-web-activity') {
|
if (window.localStorage.getItem('utm_source') === 'trusted-web-activity') {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user