Files
zkldi_Tachi/server/src/utils/auth.test.ts
T
2021-05-25 17:56:41 +01:00

133 lines
3.8 KiB
TypeScript

import {
AddNewUserAPIKey,
CreateAPIKey,
CreateInviteCode,
AddNewInvite,
ReinstateInvite,
ValidateCaptcha,
} from "./auth";
import t from "tap";
import db, { CloseMongoConnection } from "../external/mongo/db";
import { PrivateUserDocument } from "kamaitachi-common";
import { prAssert } from "../test-utils/asserts";
import Prudence from "prudence";
import ResetDBState from "../test-utils/reset-db-state";
import { MockFetch } from "../test-utils/mock-fetch";
t.test("#CreateAPIKey", (t) => {
t.match(
CreateAPIKey(),
/[0-9a-f]{20}/u,
"Should return a 20 character long lowercase hex string."
);
t.end();
});
t.test("#AddNewUserAPIKey", (t) => {
t.beforeEach(ResetDBState);
t.test("Should insert a new API key into the database", async (t) => {
const data = await AddNewUserAPIKey({ id: 1 } as PrivateUserDocument);
t.not(data, null, "Return is not null");
prAssert(
data,
{
_id: Prudence.any, // lazy
apiKey: Prudence.regex(/[0-9a-f]{20}/u),
assignedTo: Prudence.is(1),
expireTime: Prudence.is(3176708633264),
permissions: {
selfkey: Prudence.is(true),
admin: Prudence.is(false),
},
},
"Data should match a public API key object"
);
const inDatabase = await db["public-api-keys"].findOne({
_id: data._id,
});
t.strictSame(data, inDatabase, "Data from database is identical to data returned");
t.end();
});
t.end();
});
t.test("#ReinstateInvite", (t) => {
t.beforeEach(ResetDBState);
t.test("Should change the 'consumed' property of an invite to true.", async (t) => {
// mock insert
const inviteDoc = await db.invites.insert({
code: "foobar",
consumed: true,
createdBy: 1,
createdOn: 1,
});
const response = await ReinstateInvite(inviteDoc);
t.equal(response.nModified, 1, "Should modify one document");
const invite2 = await db.invites.findOne({
code: inviteDoc.code, // lol
});
t.equal(invite2!.consumed, false, "Should no longer be consumed");
t.end();
});
t.end();
});
t.test("#CreateInviteCode", (t) => {
t.match(CreateInviteCode(), /^[0-9a-f]{40}$/u, "Invite should be a 40 character hex string.");
t.end();
});
t.test("#AddNewInvite", (t) => {
t.beforeEach(ResetDBState);
t.test("Should create a new invite from a given user", async (t) => {
const userDoc = await db.users.findOne({ id: 1 });
const result = await AddNewInvite(userDoc!);
t.equal(result.createdBy, userDoc!.id, "Invite should be created by the requesting user.");
t.equal(result.consumed, false, "Invite should not be consumed.");
// was created +/- 6 seconds from now. This is perhaps too lenient, but we're only really testing its just around now ish.
t.ok(Math.abs(result.createdOn - Date.now()) <= 6000, "Invite was created roughly now.");
t.match(result.code, /^[0-9a-f]{40}$/u, "Invite code should be a 40 character hex string.");
});
t.end();
});
t.test("#ValidateCaptcha", async (t) => {
t.equal(
await ValidateCaptcha("200", "bar", MockFetch({ status: 200 })),
true,
"Validates captcha when status return is 200"
);
t.equal(
await ValidateCaptcha("400", "bar", MockFetch({ status: 400 })),
false,
"Invalidates captcha when status return is not 200"
);
t.end();
});
t.teardown(CloseMongoConnection);