add all methods

This commit is contained in:
Laurenz Rausche 2024-05-10 19:31:09 +00:00
parent b0b8b59fcc
commit c6118eba6b
22 changed files with 298 additions and 177 deletions

21
packages/express/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 @auth-tools
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

View File

@ -0,0 +1,32 @@
{
"name": "@auth-tools/express",
"version": "0.0.1-alpha.2",
"description": "A structured authentication protocol for Javascript. (express)",
"main": "dist/index.js",
"repository": "https://github.com/auth-tools/auth-tools",
"author": "Laurenz Rausche <laurenz@laurenz-rausche.de>",
"license": "MIT",
"private": false,
"scripts": {
"build": "npm run build:remove && tsc",
"build:remove": "rimraf dist",
"local": "npm run build && ts-node-dev --respawn local/index.ts",
"prepublish": "npm run build",
"remove": "npm run build:remove && rimraf node_modules yarn.lock package-lock.json pnpm-lock.yaml"
},
"dependencies": {
"express": "^4.19.2"
},
"devDependencies": {
"@auth-tools/server": "^0.0.1-alpha.6",
"@auth-tools/express": "link:.",
"@types/express": "^4.17.21",
"rimraf": "^5.0.5",
"ts-node-dev": "^2.0.0",
"typescript": "^5.4.5"
},
"peerDependencies": {},
"files": [
"dist"
]
}

View File

@ -0,0 +1,47 @@
import { AuthServer } from "@auth-tools/server";
import { RequestHandler, Router } from "express";
import { register } from "./routes/register";
import { login } from "./routes/login";
import { logout } from "./routes/logout";
import { refresh } from "./routes/refresh";
import { check } from "./routes/check";
import { validate } from "./middleWares/validate";
export function authExpress(authServer: AuthServer): {
middleWare: { validate?: RequestHandler };
router: Router;
} {
//create router
const router = Router();
//add routes
if (authServer._internal.config.methods.register !== "removed") {
router.post("/register", register(authServer));
}
if (authServer._internal.config.methods.login !== "removed") {
router.post("/login", login(authServer));
}
if (authServer._internal.config.methods.logout !== "removed") {
router.post("/logout", logout(authServer));
}
if (authServer._internal.config.methods.refresh !== "removed") {
router.post("/refresh", refresh(authServer));
}
if (authServer._internal.config.methods.check !== "removed") {
router.post("/check", check(authServer));
}
return {
middleWare: {
validate:
authServer._internal.config.methods.validate !== "removed"
? undefined
: validate(authServer),
},
router,
};
}

View File

View File

@ -0,0 +1,28 @@
import AuthServer, { AuthServerMethod } from "@auth-tools/server";
import { RequestHandler } from "express";
const HTTP_CODES = {
1: 403,
2: 400,
3: 403,
5: 500,
};
export function validate(authServer: AuthServer): RequestHandler {
return async (req, res, next) => {
const authHeader = req.get("authorization");
const accessToken = authHeader && authHeader.split(" ")[1];
const response = await (
authServer.methods.validate as AuthServerMethod<"validate">
)({ accessToken });
if (response.error) {
return res.status(HTTP_CODES[response.codes.status]).json(response);
}
res.locals.payload = { id: response.data.id };
next();
};
}

View File

@ -0,0 +1,25 @@
import AuthServer, { AuthServerMethod } from "@auth-tools/server";
import { RequestHandler } from "express";
const HTTP_CODES = {
0: 200,
1: 403,
2: 400,
3: 403,
4: 404,
5: 403,
9: 403,
};
export function check(authServer: AuthServer): RequestHandler {
return async (req, res) => {
const response = await (
authServer.methods.check as AuthServerMethod<"check">
)(req.body);
const httpCodes =
response.errorType === "server" ? 500 : HTTP_CODES[response.codes.status];
res.status(httpCodes).json(response);
};
}

View File

@ -0,0 +1,25 @@
import AuthServer, { AuthServerMethod } from "@auth-tools/server";
import { RequestHandler } from "express";
const HTTP_CODES = {
0: 201,
1: 403,
2: 400,
3: 404,
4: 403,
5: 403,
9: 403,
};
export function login(authServer: AuthServer): RequestHandler {
return async (req, res) => {
const response = await (
authServer.methods.login as AuthServerMethod<"login">
)(req.body);
const httpCodes =
response.errorType === "server" ? 500 : HTTP_CODES[response.codes.status];
res.status(httpCodes).json(response);
};
}

View File

@ -0,0 +1,24 @@
import AuthServer, { AuthServerMethod } from "@auth-tools/server";
import { RequestHandler } from "express";
const HTTP_CODES = {
0: 200,
1: 403,
2: 400,
3: 403,
4: 404,
9: 403,
};
export function logout(authServer: AuthServer): RequestHandler {
return async (req, res) => {
const response = await (
authServer.methods.logout as AuthServerMethod<"logout">
)(req.body);
const httpCodes =
response.errorType === "server" ? 500 : HTTP_CODES[response.codes.status];
res.status(httpCodes).json(response);
};
}

View File

@ -0,0 +1,24 @@
import AuthServer, { AuthServerMethod } from "@auth-tools/server";
import { RequestHandler } from "express";
const HTTP_CODES = {
0: 200,
1: 403,
2: 400,
3: 403,
4: 404,
9: 403,
};
export function refresh(authServer: AuthServer): RequestHandler {
return async (req, res) => {
const response = await (
authServer.methods.refresh as AuthServerMethod<"refresh">
)(req.body);
const httpCodes =
response.errorType === "server" ? 500 : HTTP_CODES[response.codes.status];
res.status(httpCodes).json(response);
};
}

View File

@ -0,0 +1,27 @@
import AuthServer, { AuthServerMethod } from "@auth-tools/server";
import { RequestHandler } from "express";
const HTTP_CODES = {
0: 201,
1: 403,
2: 400,
3: 406,
4: 406,
5: 403,
6: 403,
7: 403,
9: 403,
};
export function register(authServer: AuthServer): RequestHandler {
return async (req, res) => {
const response = await (
authServer.methods.register as AuthServerMethod<"register">
)(req.body);
const httpCodes =
response.errorType === "server" ? 500 : HTTP_CODES[response.codes.status];
res.status(httpCodes).json(response);
};
}

View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ES2016",
"lib": ["ES2016"],
"module": "CommonJS",
"moduleResolution": "Node",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}

View File

@ -1,66 +0,0 @@
import DefaultLogger, { COLORS, Logger } from "@auth-tools/logger";
DefaultLogger.log("debug", `"debug" log with DefaultLogger`);
DefaultLogger.log("info", `"info" log with DefaultLogger`);
DefaultLogger.log("warn", `"warn" log with DefaultLogger`);
DefaultLogger.log("error", `"error" log with DefaultLogger`);
//set config after creation
DefaultLogger.setConfig({
disableColor: true,
formatString: "Color disabled: [%l] %d %m",
});
//log shorthands
DefaultLogger.debug(`"debug" log with DefaultLogger and updated config`);
DefaultLogger.info(`"info" log with DefaultLogger and updated config`);
DefaultLogger.warn(`"warn" log with DefaultLogger and updated config`);
DefaultLogger.error(`"error" log with DefaultLogger and updated config`);
//multiple arguments
DefaultLogger.log("error", `Argument 1`, "Argument 2");
//update config again
DefaultLogger.setConfig({ disableColor: false, formatString: "Built-In: %m" });
//builtin Methods
DefaultLogger.log("debug", DefaultLogger.color("Red", COLORS.error));
DefaultLogger.log("info", DefaultLogger.twoDigits("1"));
DefaultLogger.log("warn", DefaultLogger.currentTime());
DefaultLogger.log("error", DefaultLogger.currentDate());
//create custom logger instance
const logger2 = new Logger({
disableColor: false, //set to true to disable all colors
formatString: [
//all replacement vars:
"Vars: %t = HH:MM:SS",
"Vars: %d = YYYY-MM-DD",
"Vars: %L = LEVEL",
"Vars: %l = level",
"Vars: %m = message",
].join("\n"),
});
logger2.log("error", "Hallo");
//update config to disable debug and warn
logger2.setConfig({
formatString: "Disabled Methods: [%L] %t %m",
methods: {
debug: false,
warn: false,
},
});
logger2.debug("Shouldn't log");
logger2.info("Should log");
logger2.warn("Shouldn't log");
logger2.error("Should log");
//format string with current instance config
logger2.setConfig({
formatString: "Format String: [%m]",
});
const formatted = logger2.format("info", "MY CUSTOM STRING");
console.log(formatted);

View File

@ -1,85 +0,0 @@
import { UserData } from "@auth-tools/base";
import { Logger } from "@auth-tools/logger";
import {
AuthServer,
AuthServerConfig,
AuthServerMethod,
} from "@auth-tools/server";
const Users: UserData[] = [];
const Tokens: string[] = [];
const logger = new Logger();
const authServerConfig: AuthServerConfig = {
secrets: {
accessToken: "SECRET",
refreshToken: "SECRET",
},
};
const authServer = new AuthServer(authServerConfig, logger.log);
authServer.use("getUserByMail", ({ email }) => {
const user = Users.find((usr) => usr.email === email) || null;
return { serverError: false, user };
});
authServer.use("getUserByName", ({ username }) => {
const user = Users.find((usr) => usr.username === username) || null;
return { serverError: false, user };
});
authServer.use("storeUser", ({ user }) => {
Users.push(user);
return { serverError: false };
});
authServer.use("checkToken", ({ refreshToken }) => {
const exists = Tokens.includes(refreshToken);
return { serverError: false, exists };
});
authServer.use("storeToken", ({ refreshToken }) => {
Tokens.push(refreshToken);
return { serverError: false };
});
authServer.use("deleteToken", ({ refreshToken }) => {
Tokens.splice(Tokens.indexOf(refreshToken), 1);
return { serverError: false };
});
authServer.use("validateMail", ({ email }) => {
const isValid = email.includes("@");
return { serverError: false, isValid };
});
authServer.use("validatePassword", ({ password }) => {
const isValid = password.length >= 8;
return { serverError: false, isValid };
});
authServer.use("hashPassword", ({ password }) => {
const hashedPassword = password.split("").reverse().join("");
return { serverError: false, hashedPassword };
});
authServer.use("checkPassword", ({ password, hashedPassword }) => {
const matches = password.split("").reverse().join("") === hashedPassword;
return { serverError: false, matches };
});
authServer.use("genId", ({}) => {
const id = Users.length.toString();
return { serverError: false, id };
});
(async () => {
console.log(
await (authServer.methods.register as AuthServerMethod<"register">)({
email: "as@as",
username: "as",
password: "sd",
})
);
})();

View File

@ -1,6 +1,6 @@
{
"name": "@auth-tools/server",
"version": "0.0.1-alpha.2",
"version": "0.0.1-alpha.6",
"description": "A structured authentication protocol for Javascript. (server)",
"main": "dist/index.js",
"repository": "https://github.com/auth-tools/auth-tools",
@ -15,7 +15,7 @@
"remove": "npm run build:remove && rimraf node_modules yarn.lock package-lock.json pnpm-lock.yaml"
},
"dependencies": {
"@auth-tools/base": "^0.0.1-alpha.4",
"@auth-tools/base": "^0.0.1-alpha.8",
"jsonwebtoken": "^9.0.2"
},
"devDependencies": {

View File

@ -14,7 +14,7 @@ export function undefinedUseEvent<
return (() => {
//complain about unset use event callback
log("error", `The use "${event}" event is not defined!`);
return { ...returnData, serverError: true };
return { ...returnData, error: true };
}) as UseEventCallbacks<AuthServerUseEvents>[Event];
}
@ -23,6 +23,6 @@ export function undefinedInterceptEvent<
Event extends keyof AuthServerInterceptEvents
>(): InterceptEventCallbacks<AuthServerInterceptEvents>[Event] {
return () => {
return { serverError: false, intercepted: false, interceptCode: 0 };
return { error: false, intercepted: false, interceptCode: 0 };
};
}

View File

@ -21,14 +21,14 @@ export default async function (
email: login,
});
if (getUserByMail.serverError) return { serverError: true, user: null };
if (getUserByMail.error) return { error: true, user: null };
//get user by name with value of login
const getUserByName = await internal.useEventCallbacks.getUserByName({
username: login,
});
if (getUserByName.serverError) return { serverError: true, user: null };
if (getUserByName.error) return { error: true, user: null };
return { serverError: false, user: getUserByMail.user || getUserByName.user };
return { error: false, user: getUserByMail.user || getUserByName.user };
}

View File

@ -49,7 +49,7 @@ export function createCheck(
refreshToken,
});
if (checkToken.serverError) return authServerError();
if (checkToken.error) return authServerError();
if (!checkToken.exists) {
internal.log("debug", 'The "refreshToken" does not exist.');
@ -72,7 +72,7 @@ export function createCheck(
payload: { id: decodeAccessToken.payload.id },
});
if (intercept.serverError) return authServerError();
if (intercept.error) return authServerError();
if (intercept.intercepted)
return authError<"check", 9>(

View File

@ -38,7 +38,7 @@ export function createLogin(
const getUserByLoginLogin = await getUserByLogin(login, internal);
if (getUserByLoginLogin.serverError) return authServerError();
if (getUserByLoginLogin.error) return authServerError();
if (!getUserByLoginLogin.user) {
if (internal.config.sensitive.logs)
@ -60,7 +60,7 @@ export function createLogin(
hashedPassword: getUserByLoginLogin.user.hashedPassword,
});
if (checkPassword.serverError) return authServerError();
if (checkPassword.error) return authServerError();
if (!checkPassword.matches) {
if (internal.config.sensitive.logs)
@ -97,7 +97,7 @@ export function createLogin(
payload,
});
if (intercept.serverError) return authServerError();
if (intercept.error) return authServerError();
if (intercept.intercepted)
return authError<"login", 9>(
@ -110,7 +110,7 @@ export function createLogin(
refreshToken,
});
if (storeToken.serverError) return authServerError();
if (storeToken.error) return authServerError();
return {
error: false,

View File

@ -43,7 +43,7 @@ export function createLogout(
refreshToken,
});
if (checkToken.serverError) return authServerError();
if (checkToken.error) return authServerError();
if (!checkToken.exists) {
internal.log("debug", 'The "refreshToken" does not exist.');
@ -55,7 +55,7 @@ export function createLogout(
payload: { id: decodeRefreshToken.payload.id },
});
if (intercept.serverError) return authServerError();
if (intercept.error) return authServerError();
if (intercept.intercepted)
return authError<"logout", 9>(
@ -68,7 +68,7 @@ export function createLogout(
refreshToken,
});
if (deleteToken.serverError) return authServerError();
if (deleteToken.error) return authServerError();
return {
error: false,

View File

@ -43,7 +43,7 @@ export function createRefresh(
refreshToken,
});
if (checkToken.serverError) return authServerError();
if (checkToken.error) return authServerError();
if (!checkToken.exists) {
internal.log("debug", 'The "refreshToken" does not exist.');
@ -55,7 +55,7 @@ export function createRefresh(
payload: { id: decodeRefreshToken.payload.id },
});
if (intercept.serverError) return authServerError();
if (intercept.error) return authServerError();
if (intercept.intercepted)
return authError<"refresh", 9>(

View File

@ -42,7 +42,7 @@ export function createRegister(
email,
});
if (validateMail.serverError) return authServerError();
if (validateMail.error) return authServerError();
if (!validateMail.isValid) {
internal.log("debug", 'The "email" is malformed.');
@ -54,7 +54,7 @@ export function createRegister(
password,
});
if (validatePassword.serverError) return authServerError();
if (validatePassword.error) return authServerError();
if (!validatePassword.isValid) {
internal.log("debug", 'The "password" is too weak.');
@ -63,7 +63,7 @@ export function createRegister(
const getUserByLoginEmail = await getUserByLogin(email, internal);
if (getUserByLoginEmail.serverError) return authServerError();
if (getUserByLoginEmail.error) return authServerError();
if (getUserByLoginEmail.user) {
if (internal.config.sensitive.logs)
@ -77,7 +77,7 @@ export function createRegister(
const getUserByLoginName = await getUserByLogin(username, internal);
if (getUserByLoginName.serverError) return authServerError();
if (getUserByLoginName.error) return authServerError();
if (getUserByLoginName.user) {
if (internal.config.sensitive.logs)
@ -96,14 +96,14 @@ export function createRegister(
password,
});
if (hashPassword.serverError) return authServerError();
if (hashPassword.error) return authServerError();
const genId = await internal.useEventCallbacks.genId({
email,
username,
});
if (genId.serverError) return authServerError();
if (genId.error) return authServerError();
const user: User<"id" | "email" | "username" | "hashedPassword"> = {
id: genId.id,
@ -116,7 +116,7 @@ export function createRegister(
user,
});
if (intercept.serverError) return authServerError();
if (intercept.error) return authServerError();
if (intercept.intercepted)
return authError<"register", 9>(
@ -127,7 +127,7 @@ export function createRegister(
const storeUser = await internal.useEventCallbacks.storeUser({ user });
if (storeUser.serverError) return authServerError();
if (storeUser.error) return authServerError();
return {
error: false,