@dehwyyy/auth 1.0.4 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/client/client.js +1 -1
  2. package/dist/client/middleware.d.ts +5 -0
  3. package/dist/client/middleware.js +19 -1
  4. package/dist/v2/auth/client/baseClient.d.ts +2 -0
  5. package/dist/v2/auth/client/baseClient.js +11 -0
  6. package/dist/v2/auth/client/client.d.ts +3 -0
  7. package/dist/v2/auth/client/client.js +7 -0
  8. package/dist/v2/auth/client/index.d.ts +3 -0
  9. package/dist/v2/auth/client/index.js +3 -0
  10. package/dist/v2/auth/service/baseService.d.ts +13 -0
  11. package/dist/v2/auth/service/baseService.js +54 -0
  12. package/dist/v2/auth/service/index.d.ts +3 -0
  13. package/dist/v2/auth/service/index.js +3 -0
  14. package/dist/v2/auth/service/service.d.ts +10 -0
  15. package/dist/v2/auth/service/service.js +48 -0
  16. package/dist/v2/client/builder/builder.d.ts +7 -0
  17. package/dist/v2/client/builder/builder.js +14 -0
  18. package/dist/v2/client/builder/index.d.ts +2 -0
  19. package/dist/v2/client/builder/index.js +2 -0
  20. package/dist/v2/client/client.d.ts +13 -0
  21. package/dist/v2/client/client.js +23 -0
  22. package/dist/v2/client/index.d.ts +4 -0
  23. package/dist/v2/client/index.js +4 -0
  24. package/dist/v2/client/middleware/builder.d.ts +12 -0
  25. package/dist/v2/client/middleware/builder.js +30 -0
  26. package/dist/v2/client/middleware/index.d.ts +2 -0
  27. package/dist/v2/client/middleware/index.js +2 -0
  28. package/dist/v2/client/middleware/middleware.d.ts +7 -0
  29. package/dist/v2/client/middleware/middleware.js +39 -0
  30. package/dist/v2/index.d.ts +5 -0
  31. package/dist/v2/index.js +5 -0
  32. package/dist/v2/pkg/localStorage/index.d.ts +2 -0
  33. package/dist/v2/pkg/localStorage/index.js +2 -0
  34. package/dist/v2/pkg/localStorage/localStorage.d.ts +8 -0
  35. package/dist/v2/pkg/localStorage/localStorage.js +15 -0
  36. package/dist/v2/pkg/types/authClient.d.ts +3 -0
  37. package/dist/v2/pkg/types/authClient.js +1 -0
  38. package/dist/v2/pkg/types/authService.d.ts +11 -0
  39. package/dist/v2/pkg/types/authService.js +1 -0
  40. package/dist/v2/pkg/types/index.d.ts +3 -0
  41. package/dist/v2/pkg/types/index.js +1 -0
  42. package/dist/v2/vue/router-guard/guard.d.ts +24 -0
  43. package/dist/v2/vue/router-guard/guard.js +72 -0
  44. package/dist/v2/vue/router-guard/index.d.ts +1 -0
  45. package/dist/v2/vue/router-guard/index.js +1 -0
  46. package/package.json +8 -3
  47. package/README.md +0 -50
@@ -8,7 +8,7 @@ export const getClient = (app, baseUrl, redirectBaseUrl, redirectUriPrefix = "")
8
8
  credentials: 'include',
9
9
  });
10
10
  const middleware = new Middleware(app, baseUrl, redirectBaseUrl, redirectUriPrefix);
11
- client.use(middleware.AuthorizationHeaderAttacher, middleware.TokenRefresher);
11
+ client.use(middleware.RequestCloner, middleware.AuthorizationHeaderAttacher, middleware.TokenRefresher);
12
12
  }
13
13
  return client;
14
14
  };
@@ -5,6 +5,11 @@ export declare class Middleware {
5
5
  private redirectBaseUrl;
6
6
  private redirectUriPrefix;
7
7
  constructor(app: string, baseUrl: string, redirectBaseUrl: string, redirectUriPrefix?: string);
8
+ /**
9
+ * Middleware для предварительного клонирования запросов с телом.
10
+ * Этот клон будет использован для повторной попытки в случае 401.
11
+ */
12
+ get RequestCloner(): OpenAPIMiddleware;
8
13
  get AuthorizationHeaderAttacher(): OpenAPIMiddleware;
9
14
  get TokenRefresher(): OpenAPIMiddleware;
10
15
  }
@@ -10,6 +10,23 @@ export class Middleware {
10
10
  this.redirectBaseUrl = redirectBaseUrl;
11
11
  this.redirectUriPrefix = redirectUriPrefix;
12
12
  }
13
+ /**
14
+ * Middleware для предварительного клонирования запросов с телом.
15
+ * Этот клон будет использован для повторной попытки в случае 401.
16
+ */
17
+ get RequestCloner() {
18
+ return {
19
+ async onRequest({ request }) {
20
+ // Клонируем только запросы, которые могут иметь тело
21
+ const methodsWithBody = ['POST', 'PUT', 'PATCH', 'DELETE'];
22
+ if (methodsWithBody.includes(request.method.toUpperCase())) {
23
+ request._clone = request.clone();
24
+ console.log('cloned');
25
+ }
26
+ return request;
27
+ },
28
+ };
29
+ }
13
30
  get AuthorizationHeaderAttacher() {
14
31
  const auth = GetAuthService(this.app, this.baseUrl, this.redirectBaseUrl, this.redirectUriPrefix);
15
32
  return {
@@ -26,7 +43,8 @@ export class Middleware {
26
43
  return response;
27
44
  }
28
45
  const auth = GetAuthService(t.app, t.baseUrl, t.redirectBaseUrl, t.redirectUriPrefix);
29
- return auth.RefreshAndRetry(request, response);
46
+ const requestToRetry = request._clone || request;
47
+ return auth.RefreshAndRetry(requestToRetry, response);
30
48
  },
31
49
  };
32
50
  }
@@ -0,0 +1,2 @@
1
+ import { HttpAuthClient } from '../../../v2/pkg/types';
2
+ export declare const BaseAuthClientInstance: (baseUrl: string) => HttpAuthClient;
@@ -0,0 +1,11 @@
1
+ import createClient from 'openapi-fetch';
2
+ let baseClient = null;
3
+ export const BaseAuthClientInstance = (baseUrl) => {
4
+ if (!baseClient) {
5
+ baseClient = createClient({
6
+ baseUrl,
7
+ credentials: 'include',
8
+ });
9
+ }
10
+ return baseClient;
11
+ };
@@ -0,0 +1,3 @@
1
+ import { BaseAuthService } from "../../../v2/pkg/types";
2
+ import { paths } from "@dehwyyy/auth/v2/pkg/types/schema";
3
+ export declare const CreateAuthClientInstance: (baseURL: string, baseAuthService: BaseAuthService) => import("openapi-fetch").Client<paths, `${string}/${string}`>;
@@ -0,0 +1,7 @@
1
+ import { ClientBuilder, MiddlewareBuilder } from "../../../v2/client";
2
+ export const CreateAuthClientInstance = (baseURL, baseAuthService) => new ClientBuilder().
3
+ withMiddleware(...new MiddlewareBuilder(baseAuthService).buildDefault()).
4
+ build({
5
+ baseUrl: baseURL,
6
+ credentials: 'include',
7
+ });
@@ -0,0 +1,3 @@
1
+ import { BaseAuthClientInstance } from "../../../v2/auth/client/baseClient";
2
+ import { CreateAuthClientInstance } from "../../../v2/auth/client/client";
3
+ export { BaseAuthClientInstance, CreateAuthClientInstance };
@@ -0,0 +1,3 @@
1
+ import { BaseAuthClientInstance } from "../../../v2/auth/client/baseClient";
2
+ import { CreateAuthClientInstance } from "../../../v2/auth/client/client";
3
+ export { BaseAuthClientInstance, CreateAuthClientInstance };
@@ -0,0 +1,13 @@
1
+ import { HttpAuthClient, BaseAuthService as IBaseAuthService } from "../../../v2/pkg/types";
2
+ export declare class BaseAuthService implements IBaseAuthService {
3
+ private httpAuthClient;
4
+ private refreshPromise;
5
+ constructor(httpAuthClient: HttpAuthClient);
6
+ /**
7
+ * @description Refresh access token
8
+ * @returns `accessToken` -> refresh ok. `null` -> refresh failed
9
+ **/
10
+ private doRefresh;
11
+ Refresh(): Promise<string | null>;
12
+ RequestWithAccessToken(req: Request, token?: string | null): Request;
13
+ }
@@ -0,0 +1,54 @@
1
+ import { Storage, StorageKey } from "../../../v2/pkg/localStorage";
2
+ export class BaseAuthService {
3
+ httpAuthClient;
4
+ // @Info Holds the current refresh promise
5
+ // @Returns the new access token or null
6
+ refreshPromise = null;
7
+ constructor(httpAuthClient) {
8
+ this.httpAuthClient = httpAuthClient;
9
+ }
10
+ /**
11
+ * @description Refresh access token
12
+ * @returns `accessToken` -> refresh ok. `null` -> refresh failed
13
+ **/
14
+ async doRefresh() {
15
+ const { data, error } = await this.httpAuthClient.POST('/auth/refresh');
16
+ if (error) {
17
+ console.error('Refresh error:', error);
18
+ Storage.Delete(StorageKey.ACCESS_TOKEN);
19
+ return null;
20
+ }
21
+ if (data?.accessToken) {
22
+ Storage.Set(StorageKey.ACCESS_TOKEN, data.accessToken);
23
+ return data.accessToken;
24
+ }
25
+ Storage.Delete(StorageKey.ACCESS_TOKEN);
26
+ return null;
27
+ }
28
+ async Refresh() {
29
+ if (!this.refreshPromise) {
30
+ this.refreshPromise = this.doRefresh();
31
+ }
32
+ let token = null;
33
+ try {
34
+ token = await this.refreshPromise;
35
+ }
36
+ catch (e) {
37
+ console.error(e);
38
+ }
39
+ finally {
40
+ this.refreshPromise = null;
41
+ }
42
+ if (!token) {
43
+ return null;
44
+ }
45
+ return token;
46
+ }
47
+ RequestWithAccessToken(req, token = null) {
48
+ token ??= Storage.Get(StorageKey.ACCESS_TOKEN);
49
+ if (token) {
50
+ req.headers.set('Authorization', `Bearer ${token}`);
51
+ }
52
+ return req;
53
+ }
54
+ }
@@ -0,0 +1,3 @@
1
+ import { BaseAuthService } from "../../../v2/auth/service/baseService";
2
+ import { AuthService } from "../../../v2/auth/service/service";
3
+ export { AuthService, BaseAuthService };
@@ -0,0 +1,3 @@
1
+ import { BaseAuthService } from "../../../v2/auth/service/baseService";
2
+ import { AuthService } from "../../../v2/auth/service/service";
3
+ export { AuthService, BaseAuthService };
@@ -0,0 +1,10 @@
1
+ import { BaseAuthService, GetMeResponse, HttpAuthClient, AuthService as IAuthService } from "../../../v2/pkg/types";
2
+ export declare class AuthService implements IAuthService {
3
+ private baseAuthClient;
4
+ private authClient;
5
+ private loginUrl;
6
+ constructor(baseAuthClient: BaseAuthService, authClient: HttpAuthClient, loginUrl: string);
7
+ Login(callbackUrl: string, app: string): void;
8
+ Logout(): Promise<void>;
9
+ GetMe(app: string, verbose?: boolean): Promise<GetMeResponse | null>;
10
+ }
@@ -0,0 +1,48 @@
1
+ import { Storage, StorageKey } from "../../../v2/pkg/localStorage";
2
+ export class AuthService {
3
+ baseAuthClient;
4
+ authClient;
5
+ loginUrl;
6
+ constructor(baseAuthClient, authClient, loginUrl) {
7
+ this.baseAuthClient = baseAuthClient;
8
+ this.authClient = authClient;
9
+ this.loginUrl = loginUrl;
10
+ }
11
+ Login(callbackUrl, app) {
12
+ window.location.href = `${this.loginUrl}?app=${app}&redirect_uri=${callbackUrl}`;
13
+ }
14
+ async Logout() {
15
+ Storage.Delete(StorageKey.ACCESS_TOKEN);
16
+ const { response, error } = await this.authClient.POST('/auth/logout');
17
+ if (error || !response.ok) {
18
+ console.error(error, response);
19
+ return Promise.reject(error);
20
+ }
21
+ }
22
+ async GetMe(app, verbose = false) {
23
+ let token = Storage.Get(StorageKey.ACCESS_TOKEN);
24
+ if (!token) {
25
+ token = await this.baseAuthClient.Refresh();
26
+ if (!token) {
27
+ return null;
28
+ }
29
+ }
30
+ const { data, error } = await this.authClient.GET("/auth/me", {
31
+ params: {
32
+ query: {
33
+ app,
34
+ verbose: verbose ? "all" : "none",
35
+ }
36
+ }
37
+ });
38
+ if (error) {
39
+ console.error(error);
40
+ return null;
41
+ }
42
+ if (!data || !data.user_id) {
43
+ console.warn("Failed to get user info:", data);
44
+ return null;
45
+ }
46
+ return data;
47
+ }
48
+ }
@@ -0,0 +1,7 @@
1
+ import createClient, { ClientOptions, Middleware as OpenAPIMiddleware } from "openapi-fetch";
2
+ export declare class ClientBuilder<OpenAPIClientDefinitions extends {}> {
3
+ private middlewares;
4
+ constructor();
5
+ withMiddleware(...middlewares: OpenAPIMiddleware[]): this;
6
+ build(opts?: ClientOptions): ReturnType<typeof createClient<OpenAPIClientDefinitions>>;
7
+ }
@@ -0,0 +1,14 @@
1
+ import createClient from "openapi-fetch";
2
+ export class ClientBuilder {
3
+ middlewares = [];
4
+ constructor() { }
5
+ withMiddleware(...middlewares) {
6
+ this.middlewares = this.middlewares.concat(middlewares);
7
+ return this;
8
+ }
9
+ build(opts) {
10
+ const client = createClient(opts);
11
+ client.use(...this.middlewares);
12
+ return client;
13
+ }
14
+ }
@@ -0,0 +1,2 @@
1
+ import { ClientBuilder } from "../../../v2/client/builder/builder";
2
+ export { ClientBuilder };
@@ -0,0 +1,2 @@
1
+ import { ClientBuilder } from "../../../v2/client/builder/builder";
2
+ export { ClientBuilder };
@@ -0,0 +1,13 @@
1
+ import createClient, { ClientOptions, Middleware as OpenAPIMiddleware } from "openapi-fetch";
2
+ type Client = ReturnType<typeof createClient<{}>>;
3
+ export declare class ClientInstance {
4
+ private static map;
5
+ New<T extends Client>(key: string, clientFactory: () => T): T;
6
+ }
7
+ export declare class ClientBuilder<OpenAPIClientDefinitions extends {}> {
8
+ private middlewares;
9
+ constructor();
10
+ withMiddleware(...middlewares: OpenAPIMiddleware[]): this;
11
+ build(opts: ClientOptions): ReturnType<typeof createClient<OpenAPIClientDefinitions>>;
12
+ }
13
+ export {};
@@ -0,0 +1,23 @@
1
+ import createClient from "openapi-fetch";
2
+ export class ClientInstance {
3
+ static map = new Map();
4
+ New(key, clientFactory) {
5
+ if (!ClientInstance.map.has(key)) {
6
+ ClientInstance.map.set(key, clientFactory());
7
+ }
8
+ return ClientInstance.map.get(key);
9
+ }
10
+ }
11
+ export class ClientBuilder {
12
+ middlewares = [];
13
+ constructor() { }
14
+ withMiddleware(...middlewares) {
15
+ this.middlewares = this.middlewares.concat(middlewares);
16
+ return this;
17
+ }
18
+ build(opts) {
19
+ const client = createClient(opts);
20
+ client.use(...this.middlewares);
21
+ return client;
22
+ }
23
+ }
@@ -0,0 +1,4 @@
1
+ import { ClientBuilder } from "./builder";
2
+ import { ClientInstance } from "./client";
3
+ import { MiddlewareBuilder } from "./middleware";
4
+ export { ClientBuilder, ClientInstance, MiddlewareBuilder };
@@ -0,0 +1,4 @@
1
+ import { ClientBuilder } from "./builder";
2
+ import { ClientInstance } from "./client";
3
+ import { MiddlewareBuilder } from "./middleware";
4
+ export { ClientBuilder, ClientInstance, MiddlewareBuilder };
@@ -0,0 +1,12 @@
1
+ import { BaseAuthService } from '../../../v2/pkg/types';
2
+ import type { Middleware as OpenAPIMiddleware } from 'openapi-fetch';
3
+ export declare class MiddlewareBuilder {
4
+ private service;
5
+ private middlewares;
6
+ constructor(service: BaseAuthService);
7
+ withRequestClone(): this;
8
+ withAccessToken(): this;
9
+ withAutoRefresh(): this;
10
+ buildDefault(): OpenAPIMiddleware[];
11
+ build(): OpenAPIMiddleware[];
12
+ }
@@ -0,0 +1,30 @@
1
+ import { Middleware } from '../../../v2/client/middleware/middleware';
2
+ export class MiddlewareBuilder {
3
+ service;
4
+ middlewares = new Set();
5
+ constructor(service) {
6
+ this.service = service;
7
+ }
8
+ withRequestClone() {
9
+ this.middlewares.add(Middleware.requestClone());
10
+ return this;
11
+ }
12
+ withAccessToken() {
13
+ this.middlewares.add(Middleware.accessTokenAttacher(this.service));
14
+ return this;
15
+ }
16
+ withAutoRefresh() {
17
+ this.middlewares.add(Middleware.autoRefresh(this.service));
18
+ return this;
19
+ }
20
+ buildDefault() {
21
+ return [
22
+ Middleware.requestClone(),
23
+ Middleware.accessTokenAttacher(this.service),
24
+ Middleware.autoRefresh(this.service),
25
+ ];
26
+ }
27
+ build() {
28
+ return Array.from(this.middlewares);
29
+ }
30
+ }
@@ -0,0 +1,2 @@
1
+ import { MiddlewareBuilder } from "../../../v2/client/middleware/builder";
2
+ export { MiddlewareBuilder };
@@ -0,0 +1,2 @@
1
+ import { MiddlewareBuilder } from "../../../v2/client/middleware/builder";
2
+ export { MiddlewareBuilder };
@@ -0,0 +1,7 @@
1
+ import { BaseAuthService } from '../../../v2/pkg/types';
2
+ import type { Middleware as OpenAPIMiddleware } from 'openapi-fetch';
3
+ export declare class Middleware {
4
+ static requestClone(): OpenAPIMiddleware;
5
+ static accessTokenAttacher(service: BaseAuthService): OpenAPIMiddleware;
6
+ static autoRefresh(service: BaseAuthService): OpenAPIMiddleware;
7
+ }
@@ -0,0 +1,39 @@
1
+ export class Middleware {
2
+ static requestClone() {
3
+ return {
4
+ async onRequest({ request }) {
5
+ const methodsWithBody = ['POST', 'PUT', 'PATCH', 'DELETE'];
6
+ if (methodsWithBody.includes(request.method.toUpperCase())) {
7
+ request._clone = request.clone();
8
+ }
9
+ return request;
10
+ },
11
+ };
12
+ }
13
+ static accessTokenAttacher(service) {
14
+ return {
15
+ async onRequest({ request }) {
16
+ return service.RequestWithAccessToken(request);
17
+ }
18
+ };
19
+ }
20
+ static autoRefresh(service) {
21
+ return {
22
+ async onResponse({ response, request }) {
23
+ if (response.status !== 401 || request.url.includes('/auth/refresh')) {
24
+ return response;
25
+ }
26
+ const requestToRetry = request._clone || request;
27
+ const newAccessToken = await service.Refresh()
28
+ .catch((e) => {
29
+ console.error('failed to refresh', e);
30
+ return null;
31
+ });
32
+ if (!newAccessToken) {
33
+ return response;
34
+ }
35
+ return fetch(service.RequestWithAccessToken(requestToRetry, newAccessToken));
36
+ },
37
+ };
38
+ }
39
+ }
@@ -0,0 +1,5 @@
1
+ import { BaseAuthClientInstance, CreateAuthClientInstance } from "../v2/auth/client";
2
+ import { AuthService, BaseAuthService } from "../v2/auth/service";
3
+ import { ClientBuilder, ClientInstance, MiddlewareBuilder } from "../v2/client";
4
+ import { RouterAuthGuard } from "../v2/vue/router-guard";
5
+ export { AuthService, BaseAuthClientInstance, BaseAuthService, ClientBuilder, ClientInstance, CreateAuthClientInstance, MiddlewareBuilder, RouterAuthGuard };
@@ -0,0 +1,5 @@
1
+ import { BaseAuthClientInstance, CreateAuthClientInstance } from "../v2/auth/client";
2
+ import { AuthService, BaseAuthService } from "../v2/auth/service";
3
+ import { ClientBuilder, ClientInstance, MiddlewareBuilder } from "../v2/client";
4
+ import { RouterAuthGuard } from "../v2/vue/router-guard";
5
+ export { AuthService, BaseAuthClientInstance, BaseAuthService, ClientBuilder, ClientInstance, CreateAuthClientInstance, MiddlewareBuilder, RouterAuthGuard };
@@ -0,0 +1,2 @@
1
+ import { Storage, StorageKey } from "../../../v2/pkg/localStorage/localStorage";
2
+ export { Storage, StorageKey };
@@ -0,0 +1,2 @@
1
+ import { Storage, StorageKey } from "../../../v2/pkg/localStorage/localStorage";
2
+ export { Storage, StorageKey };
@@ -0,0 +1,8 @@
1
+ export declare const enum StorageKey {
2
+ ACCESS_TOKEN = "accessToken"
3
+ }
4
+ export declare class Storage {
5
+ static Set(key: StorageKey, value: string): void;
6
+ static Delete(key: StorageKey): void;
7
+ static Get(key: StorageKey): string | null;
8
+ }
@@ -0,0 +1,15 @@
1
+ export var StorageKey;
2
+ (function (StorageKey) {
3
+ StorageKey["ACCESS_TOKEN"] = "accessToken";
4
+ })(StorageKey || (StorageKey = {}));
5
+ export class Storage {
6
+ static Set(key, value) {
7
+ localStorage.setItem(key, value);
8
+ }
9
+ static Delete(key) {
10
+ localStorage.removeItem(key);
11
+ }
12
+ static Get(key) {
13
+ return localStorage.getItem(key);
14
+ }
15
+ }
@@ -0,0 +1,3 @@
1
+ import { paths } from "@dehwyyy/auth/v2/pkg/types/schema";
2
+ import createClient from "openapi-fetch";
3
+ export type HttpAuthClient = ReturnType<typeof createClient<paths>>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { components } from "@dehwyyy/auth/v2/pkg/types/schema";
2
+ export interface BaseAuthService {
3
+ RequestWithAccessToken(req: Request, token?: string | null): Request;
4
+ Refresh(): Promise<string | null>;
5
+ }
6
+ export type GetMeResponse = components["schemas"]["GetMeResponse"];
7
+ export interface AuthService {
8
+ Login(callbackUrl: string, app: string): void;
9
+ Logout(): Promise<void>;
10
+ GetMe(app: string, verbose?: boolean): Promise<GetMeResponse | null>;
11
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { HttpAuthClient } from "../../../v2/pkg/types/authClient";
2
+ import type { AuthService, BaseAuthService, GetMeResponse } from "../../../v2/pkg/types/authService";
3
+ export { AuthService, BaseAuthService, GetMeResponse, HttpAuthClient };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import { components } from "@dehwyyy/auth/client/schema";
2
+ import { AuthService } from "../../../v2/pkg/types";
3
+ type User = Omit<components["schemas"]["GetMeResponse"], "info">;
4
+ interface RouterAuthGuardProps {
5
+ app: string;
6
+ cacheTTL: number;
7
+ onGetMe: (data: User | null) => void;
8
+ fallbackPage: string;
9
+ baseServiceURL: string;
10
+ }
11
+ type DynamicUnauthorizedRedirect = {
12
+ to: string;
13
+ roles: string[];
14
+ }[];
15
+ export declare class RouterAuthGuard {
16
+ private authService;
17
+ private props;
18
+ private getMeCache;
19
+ constructor(authService: AuthService, props: RouterAuthGuardProps);
20
+ Authorized(roles?: string[]): (to: any, from: any) => Promise<string | boolean>;
21
+ Unauthorized(redirectProps: DynamicUnauthorizedRedirect): (_: any, __: any) => Promise<string | true>;
22
+ private RolesIntercept;
23
+ }
24
+ export {};
@@ -0,0 +1,72 @@
1
+ export class RouterAuthGuard {
2
+ authService;
3
+ props;
4
+ getMeCache = null;
5
+ constructor(authService, props) {
6
+ this.authService = authService;
7
+ this.props = props;
8
+ if (props.app === "") {
9
+ throw new Error("App should be provided in props");
10
+ }
11
+ }
12
+ Authorized(roles = []) {
13
+ return async (to, from) => {
14
+ // If cache is valid
15
+ if (this.getMeCache && this.getMeCache.expiresAt > Date.now()) {
16
+ return this.RolesIntercept(roles, this.getMeCache.data.roles || []);
17
+ }
18
+ try {
19
+ const data = await this.authService.GetMe(this.props.app);
20
+ this.props.onGetMe(data);
21
+ if (!data) {
22
+ this.getMeCache = null;
23
+ this.authService.Login(this.props.baseServiceURL + to.fullPath, this.props.app);
24
+ return false;
25
+ }
26
+ if (!this.RolesIntercept(roles, data.roles || [])) {
27
+ return this.props.fallbackPage;
28
+ }
29
+ this.getMeCache = {
30
+ data,
31
+ expiresAt: Date.now() + this.props.cacheTTL * 1000,
32
+ };
33
+ return true;
34
+ }
35
+ catch (e) {
36
+ console.error("failed to authorize:", e);
37
+ }
38
+ return false;
39
+ };
40
+ }
41
+ Unauthorized(redirectProps) {
42
+ return async (_, __) => {
43
+ // If cache is valid
44
+ let roles = [];
45
+ // Try to get user from cache
46
+ if (this.getMeCache && this.getMeCache.expiresAt > Date.now()) {
47
+ roles = this.getMeCache.data.roles || [];
48
+ }
49
+ else {
50
+ // Or get user from API
51
+ const user = await this.authService.GetMe(this.props.app);
52
+ this.props.onGetMe(user);
53
+ if (user) {
54
+ this.getMeCache = {
55
+ data: user,
56
+ expiresAt: Date.now() + this.props.cacheTTL * 1000,
57
+ };
58
+ roles = user.roles || [];
59
+ }
60
+ }
61
+ for (const { to, roles: requiredRoles } of redirectProps) {
62
+ if (this.RolesIntercept(requiredRoles, roles)) {
63
+ return to;
64
+ }
65
+ }
66
+ return true;
67
+ };
68
+ }
69
+ RolesIntercept(requiredRoles, userRoles) {
70
+ return requiredRoles.filter(role => userRoles.includes(role)).length !== 0;
71
+ }
72
+ }
@@ -0,0 +1 @@
1
+ export { RouterAuthGuard } from "../../../v2/vue/router-guard/guard";
@@ -0,0 +1 @@
1
+ export { RouterAuthGuard } from "../../../v2/vue/router-guard/guard";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dehwyyy/auth",
3
- "version": "1.0.4",
3
+ "version": "1.0.7",
4
4
  "private": false,
5
5
  "description": "dehwyyy auth utilities",
6
6
  "type": "module",
@@ -10,6 +10,10 @@
10
10
  ".": {
11
11
  "import": "./dist/index.js"
12
12
  },
13
+ "./v2": {
14
+ "import": "./dist/v2/index.js",
15
+ "types": "./dist/v2/index.d.ts"
16
+ },
13
17
  "./guard": {
14
18
  "import": "./dist/guard/index.js"
15
19
  }
@@ -18,10 +22,10 @@
18
22
  "dist"
19
23
  ],
20
24
  "scripts": {
21
- "build": "tsc",
25
+ "build": "tsc && tsc-alias",
22
26
  "prepack": "npm run build",
23
27
  "lint": "prettier --check .",
24
- "ts": "tsc",
28
+ "ts": "tsc && tsc-alias",
25
29
  "format": "prettier --write ."
26
30
  },
27
31
  "engines": {
@@ -36,6 +40,7 @@
36
40
  "license": "MIT",
37
41
  "devDependencies": {
38
42
  "prettier": "^3.0.0",
43
+ "tsc-alias": "^1.8.16",
39
44
  "typescript": "5.8.2"
40
45
  },
41
46
  "dependencies": {
package/README.md DELETED
@@ -1,50 +0,0 @@
1
- ## TokenAttacher & TokenRefresher middleware usage
2
-
3
- ```ts
4
- import { GetAuthService } from "@dehwyyy/auth";
5
- import type { Middleware } from "openapi-fetch";
6
-
7
- export const AuthorizationHeaderAttacherMiddleware: Middleware = {
8
- async onRequest({ request }) {
9
- return GetAuthService(APP, BASE_URL).WithAuthorizationToken(request);
10
- },
11
- }
12
-
13
- export const TokenRefresherMiddleware: Middleware = {
14
- async onResponse({ response, request }) {
15
- if (response.status !== 401 || request.url.includes('/auth/refresh')) {
16
- return response;
17
- }
18
-
19
- return GetAuthService(APP, BASE_URL).RefreshAndRetry(request, response);
20
- }
21
- }
22
-
23
-
24
- ```
25
-
26
- ## Guard usage example
27
-
28
- ```ts
29
- import { Guards } from '@dehwyyy/auth/guard';
30
- import { createRouter, createWebHistory } from 'vue-router';
31
-
32
- enum Roles {
33
- ADMIN = "Admin",
34
- MANAGER = "Manager",
35
- USER = "User"
36
- }
37
-
38
- const g = new Guards(APP, BASE_URL, "/login")
39
-
40
- export const router = createRouter({
41
- history: createWebHistory(import.meta.env.VITE_BASE_URL),
42
- routes: [
43
- { path: "/login", name: "Login", component: Login },
44
- { path: "/dashboard", name: "DashboardIndex", component: View, beforeEnter: g.Auth([Roles.USER]) },
45
- { path: "/dashboard/users", name: "DashboardUsers", component: Users, beforeEnter: g.Auth([Roles.ADMIN, Roles.MANAGER]) },
46
- { path: "/:pathMatch(.*)*", redirect: "/login" },
47
- ],
48
- });
49
-
50
- ```