This commit is contained in:
Laurenz Rausche 2024-05-10 19:30:55 +00:00
parent 5ad713bb75
commit b0b8b59fcc
16 changed files with 319 additions and 7 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@auth-tools/base",
"version": "0.0.1-alpha.4",
"version": "0.0.1-alpha.8",
"description": "A structured authentication protocol for Javascript. (base)",
"main": "dist/index.js",
"repository": "https://github.com/auth-tools/auth-tools",

View File

@ -14,7 +14,7 @@ export type InterceptEventsDefinition = {
type InterceptEvent<ClassInterceptEvents extends InterceptEventDefinition> = {
data: ClassInterceptEvents["data"];
return: {
serverError?: boolean;
error?: boolean;
intercepted: boolean;
interceptCode: number;
};

View File

@ -14,7 +14,7 @@ export type UseEventsDefinition = {
//data for an use event
type UseEvent<ClassUseEvents extends UseEventDefinition> = {
data: ClassUseEvents["data"];
return: { serverError?: boolean } & ClassUseEvents["return"];
return: { error?: boolean } & ClassUseEvents["return"];
};
//all use events

View File

@ -83,7 +83,6 @@ export type AuthProtocol = {
validate_1: AuthResponseBuilder<"validate", 1, null>;
validate_2: AuthResponseBuilder<"validate", 2, null>;
validate_3: AuthResponseBuilder<"validate", 3, null>;
validate_9: AuthResponseBuilder<"validate", 9, null, number>;
}
>;
register: AuthMethodBuilder<

View File

@ -5,7 +5,6 @@ export type AuthMessages = {
validate_1: "The validation method is disabled.";
validate_2: 'The "accessToken" is missing.';
validate_3: 'The "accessToken" is invalid.';
validate_9: "The validation request was intercepted.";
register_0: "Registration successful.";
register_1: "The registration method is disabled.";
register_2: 'The "email", "username" or "password" is missing.';

View File

@ -1,6 +1,6 @@
{
"name": "@auth-tools/client",
"version": "0.0.0",
"version": "0.0.1-alpha.3",
"description": "A structured authentication protocol for Javascript. (client)",
"main": "dist/index.js",
"repository": "https://github.com/auth-tools/auth-tools",
@ -14,9 +14,12 @@
"prepublish": "npm run build",
"remove": "npm run build:remove && rimraf node_modules yarn.lock package-lock.json pnpm-lock.yaml"
},
"dependencies": {},
"dependencies": {
"@auth-tools/base": "^0.0.1-alpha.8"
},
"devDependencies": {
"@auth-tools/client": "link:.",
"@auth-tools/logger": "^0.0.1-alpha.1",
"rimraf": "^5.0.5",
"ts-node-dev": "^2.0.0",
"typescript": "^5.4.5"

View File

@ -0,0 +1,92 @@
import {
AuthBase,
AuthProtocol,
AuthRequest,
AuthResponse,
UseEventCallbacks,
User,
} from "@auth-tools/base";
import { LogFunction } from "@auth-tools/logger";
import { undefinedUseEvent } from "./events";
import { createValidate } from "./methods/validate";
import { createRegister } from "./methods/register";
import { createLogin } from "./methods/login";
import { createLogout } from "./methods/logout";
import { createRefresh } from "./methods/refresh";
import { createCheck } from "./methods/check";
type MethodReturn<MethodName extends keyof AuthProtocol> =
| { clientError: true; res: null }
| { clientError: false; res: AuthResponse<MethodName> };
export type AuthClientConnector<MethodName extends keyof AuthProtocol> = (
method: MethodName,
data: AuthRequest<MethodName>
) => MethodReturn<MethodName>;
type TokenTypes = "accessToken" | "refreshToken";
//config passed by user to class
export type AuthClientConfig = {
connector: AuthClientConnector<keyof AuthProtocol>;
};
//all use events
export type AuthClientUseEvents = {
getToken: {
data: { type: TokenTypes };
return: { token: User<TokenTypes>[TokenTypes] | null };
};
storeToken: {
data: { type: TokenTypes; token: User<TokenTypes>[TokenTypes] };
return: {};
};
deleteToken: {
data: { type: TokenTypes };
return: {};
};
};
export type AuthClientMethod<
MethodName extends keyof AuthProtocol,
NoData extends boolean = MethodName extends "logout" | "refresh" | "check"
? true
: false
> = (
data: NoData extends true ? {} : AuthRequest<MethodName>
) => Promise<MethodReturn<MethodName>>;
type AuthClientMethods = {
[MethodName in keyof AuthProtocol]: AuthClientMethod<MethodName>;
};
export class AuthClient extends AuthBase<
AuthClientConfig,
AuthClientUseEvents,
{}
> {
//all methods
public methods: AuthClientMethods;
constructor(config: AuthClientConfig, log: LogFunction) {
//defaults for use event callbacks
const defaultedUseEvents: UseEventCallbacks<AuthClientUseEvents> = {
getToken: undefinedUseEvent("getToken", { token: "" }, log),
storeToken: undefinedUseEvent("storeToken", {}, log),
deleteToken: undefinedUseEvent("deleteToken", {}, log),
};
//init authbase class
super(config, log, defaultedUseEvents, {});
//all auth methods
this.methods = {
validate: createValidate(this._internal),
register: createRegister(this._internal),
login: createLogin(this._internal),
logout: createLogout(this._internal),
refresh: createRefresh(this._internal),
check: createCheck(this._internal),
};
}
}

View File

@ -0,0 +1,19 @@
import { UseEventCallbacks } from "@auth-tools/base";
import { AuthClientUseEvents } from "./auth";
import { LogFunction } from "@auth-tools/logger";
//for an undefined use event
export function undefinedUseEvent<
Event extends keyof AuthClientUseEvents,
Return extends AuthClientUseEvents[Event]["return"]
>(
event: Event,
returnData: Return,
log: LogFunction
): UseEventCallbacks<AuthClientUseEvents>[Event] {
return (() => {
//complain about unset use event callback
log("error", `The use "${event}" event is not defined!`);
return { ...returnData, error: true };
}) as UseEventCallbacks<AuthClientUseEvents>[Event];
}

View File

@ -0,0 +1,7 @@
export { AuthClient as default } from "./auth";
export {
AuthClient,
AuthClientConfig,
AuthClientConnector,
AuthClientMethod,
} from "./auth";

View File

@ -0,0 +1,13 @@
import { AuthInternal } from "@auth-tools/base";
import {
AuthClientConfig,
AuthClientMethod,
AuthClientUseEvents,
} from "../auth";
//create _method method
export function create_Method(
internal: AuthInternal<AuthClientConfig, AuthClientUseEvents, {}>
): AuthClientMethod<"_method"> {
return async ({}) => {};
}

View File

@ -0,0 +1,37 @@
import { AuthInternal } from "@auth-tools/base";
import {
AuthClientConfig,
AuthClientConnector,
AuthClientMethod,
AuthClientUseEvents,
} from "../auth";
//create check method
export function createCheck(
internal: AuthInternal<AuthClientConfig, AuthClientUseEvents, {}>
): AuthClientMethod<"check"> {
return async () => {
const getRefreshToken = await internal.useEventCallbacks.getToken({
type: "refreshToken",
});
if (getRefreshToken.error || getRefreshToken.token === null)
return { clientError: true, res: null };
const getAccessToken = await internal.useEventCallbacks.getToken({
type: "accessToken",
});
if (getAccessToken.error || getAccessToken.token === null)
return { clientError: true, res: null };
const checkResponse = await (
internal.config.connector as AuthClientConnector<"check">
)("check", {
accessToken: getAccessToken.token,
refreshToken: getRefreshToken.token,
});
return checkResponse;
};
}

View File

@ -0,0 +1,33 @@
import { AuthInternal } from "@auth-tools/base";
import {
AuthClientConfig,
AuthClientConnector,
AuthClientMethod,
AuthClientUseEvents,
} from "../auth";
//create login method
export function createLogin(
internal: AuthInternal<AuthClientConfig, AuthClientUseEvents, {}>
): AuthClientMethod<"login"> {
return async ({ login, password }) => {
const loginResponse = await (
internal.config.connector as AuthClientConnector<"login">
)("login", { login, password });
if (loginResponse.clientError || loginResponse.res.error)
return loginResponse;
//store tokens
internal.useEventCallbacks.storeToken({
type: "accessToken",
token: loginResponse.res.data.accessToken,
});
internal.useEventCallbacks.storeToken({
type: "refreshToken",
token: loginResponse.res.data.refreshToken,
});
return loginResponse;
};
}

View File

@ -0,0 +1,36 @@
import { AuthInternal } from "@auth-tools/base";
import {
AuthClientConfig,
AuthClientConnector,
AuthClientMethod,
AuthClientUseEvents,
} from "../auth";
//create logout method
export function createLogout(
internal: AuthInternal<AuthClientConfig, AuthClientUseEvents, {}>
): AuthClientMethod<"logout"> {
return async () => {
const getRefreshToken = await internal.useEventCallbacks.getToken({
type: "refreshToken",
});
if (getRefreshToken.error || getRefreshToken.token === null)
return { clientError: true, res: null };
const logoutResponse = await (
internal.config.connector as AuthClientConnector<"logout">
)("logout", { refreshToken: getRefreshToken.token });
if (!logoutResponse.clientError && !logoutResponse.res.error) {
internal.useEventCallbacks.deleteToken({
type: "accessToken",
});
internal.useEventCallbacks.deleteToken({
type: "refreshToken",
});
}
return logoutResponse;
};
}

View File

@ -0,0 +1,34 @@
import { AuthInternal } from "@auth-tools/base";
import {
AuthClientConfig,
AuthClientConnector,
AuthClientMethod,
AuthClientUseEvents,
} from "../auth";
//create refresh method
export function createRefresh(
internal: AuthInternal<AuthClientConfig, AuthClientUseEvents, {}>
): AuthClientMethod<"refresh"> {
return async () => {
const getRefreshToken = await internal.useEventCallbacks.getToken({
type: "refreshToken",
});
if (getRefreshToken.error || getRefreshToken.token === null)
return { clientError: true, res: null };
const refreshResponse = await (
internal.config.connector as AuthClientConnector<"refresh">
)("refresh", { refreshToken: getRefreshToken.token });
if (!refreshResponse.clientError && !refreshResponse.res.error) {
internal.useEventCallbacks.storeToken({
type: "accessToken",
token: refreshResponse.res.data.accessToken,
});
}
return refreshResponse;
};
}

View File

@ -0,0 +1,20 @@
import { AuthInternal } from "@auth-tools/base";
import {
AuthClientConfig,
AuthClientConnector,
AuthClientMethod,
AuthClientUseEvents,
} from "../auth";
//create register method
export function createRegister(
internal: AuthInternal<AuthClientConfig, AuthClientUseEvents, {}>
): AuthClientMethod<"register"> {
return async ({ email, username, password }) => {
const registerResponse = await (
internal.config.connector as AuthClientConnector<"register">
)("register", { email, username, password });
return registerResponse;
};
}

View File

@ -0,0 +1,20 @@
import { AuthInternal } from "@auth-tools/base";
import {
AuthClientConfig,
AuthClientConnector,
AuthClientMethod,
AuthClientUseEvents,
} from "../auth";
//create validate method
export function createValidate(
internal: AuthInternal<AuthClientConfig, AuthClientUseEvents, {}>
): AuthClientMethod<"validate"> {
return async ({ accessToken }) => {
const validateResponse = await (
internal.config.connector as AuthClientConnector<"validate">
)("validate", { accessToken });
return validateResponse;
};
}