@lobb-js/lobb-ext-auth 0.3.1 → 0.4.1

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.
@@ -1,4 +1,5 @@
1
1
  import type { CollectionConfig } from "@lobb-js/core";
2
+ import { hash } from "argon2";
2
3
 
3
4
  export const usersCollection: CollectionConfig = {
4
5
  indexes: {
@@ -32,6 +33,15 @@ export const usersCollection: CollectionConfig = {
32
33
  validators: {
33
34
  required: true,
34
35
  },
36
+ hooks: {
37
+ beforeCreate: async ({ data }) => await hash(data.password),
38
+ beforeUpdate: async ({ data }) => data.password ? await hash(data.password) : undefined,
39
+ },
40
+ ui: {
41
+ input: {
42
+ type: "password",
43
+ },
44
+ },
35
45
  },
36
46
  role: {
37
47
  type: "string",
@@ -37,9 +37,10 @@ export type ExtensionConfig = {
37
37
  admin: {
38
38
  password: string;
39
39
  email: string;
40
+ [key: string]: any;
40
41
  };
41
42
  dashboard_access_roles?: string[];
42
- roles: Record<string, RolesConfig | undefined>;
43
+ roles?: Record<string, RolesConfig | undefined>;
43
44
  extend_users?: {
44
45
  indexes?: CollectionConfig["indexes"];
45
46
  fields?: Omit<CollectionConfig["fields"], "id">;
@@ -11,7 +11,7 @@ export async function init(lobb: Lobb, extensionConfig: ExtensionConfig) {
11
11
  async function syncincAdminUserInDB(lobb: Lobb, extensionConfig: ExtensionConfig) {
12
12
  // syncinc the admin user in users collection
13
13
  const config = extensionConfig;
14
- const adminUserData = config.admin;
14
+ const { email, password, ...extraFields } = config.admin;
15
15
  const entries = (await lobb.collectionService.findAll({
16
16
  collectionName: "auth_users",
17
17
  params: {
@@ -26,24 +26,26 @@ async function syncincAdminUserInDB(lobb: Lobb, extensionConfig: ExtensionConfig
26
26
  await lobb.collectionService.createOne({
27
27
  collectionName: "auth_users",
28
28
  data: {
29
- email: adminUserData.email,
30
- password: adminUserData.password,
29
+ ...extraFields,
30
+ email,
31
+ password,
31
32
  role: "admin",
32
33
  },
33
34
  });
34
35
  } else {
35
36
  const passwordIdentical = await verify(
36
37
  adminUser.password,
37
- adminUserData.password,
38
+ password,
38
39
  );
39
40
 
40
- if (adminUser.email !== adminUserData.email || !passwordIdentical) {
41
+ if (adminUser.email !== email || !passwordIdentical) {
41
42
  await lobb.collectionService.updateOne({
42
43
  collectionName: "auth_users",
43
44
  id: adminUser.id,
44
45
  data: {
45
- email: adminUserData.email,
46
- password: adminUserData.password,
46
+ ...extraFields,
47
+ email,
48
+ password,
47
49
  },
48
50
  });
49
51
  }
@@ -0,0 +1,53 @@
1
+ import type { Config } from "@lobb-js/core";
2
+ import auth from "../../index.ts";
3
+
4
+ export const authWithAdminExtraFieldsConfig: Config = {
5
+ project: {
6
+ name: "Lobb",
7
+ force_sync: true,
8
+ support_email: "support@lobb.com",
9
+ },
10
+ database: {
11
+ host: "localhost",
12
+ port: 5432,
13
+ username: "test",
14
+ password: "test",
15
+ database: "*",
16
+ },
17
+ web_server: {
18
+ host: "0.0.0.0",
19
+ port: 0,
20
+ },
21
+ extensions: [
22
+ auth({
23
+ admin: {
24
+ email: "admin@test.com",
25
+ password: "admin",
26
+ name: "Super Admin",
27
+ username: "superadmin",
28
+ },
29
+ extend_users: {
30
+ fields: {
31
+ name: {
32
+ type: "string",
33
+ length: 255,
34
+ },
35
+ username: {
36
+ type: "string",
37
+ length: 255,
38
+ },
39
+ },
40
+ },
41
+ roles: {
42
+ public: {
43
+ permissions: {
44
+ auth_users: {
45
+ read: true,
46
+ },
47
+ },
48
+ },
49
+ },
50
+ }),
51
+ ],
52
+ collections: {},
53
+ };
@@ -0,0 +1,50 @@
1
+ import { Lobb } from "@lobb-js/core";
2
+ import { afterAll, beforeAll, describe, it, expect } from "bun:test";
3
+ import { authWithAdminExtraFieldsConfig } from "../configs/auth_with_admin_extra_fields.ts";
4
+
5
+ describe("AUTH admin extra fields", () => {
6
+ let lobb: Lobb;
7
+
8
+ beforeAll(async () => {
9
+ lobb = await Lobb.init(authWithAdminExtraFieldsConfig);
10
+ });
11
+
12
+ afterAll(async () => {
13
+ await lobb.close();
14
+ });
15
+
16
+ it("should create the admin user with extra fields on first init", async () => {
17
+ const result = await lobb.collectionService.findAll({
18
+ collectionName: "auth_users",
19
+ params: { filter: { role: "admin" } },
20
+ });
21
+
22
+ const admin = result.data[0];
23
+ expect(admin).toBeDefined();
24
+ expect(admin.email).toEqual("admin@test.com");
25
+ expect(admin.role).toEqual("admin");
26
+ expect(admin.name).toEqual("Super Admin");
27
+ expect(admin.username).toEqual("superadmin");
28
+ });
29
+
30
+ it("should always set role to admin regardless of extra fields", async () => {
31
+ const result = await lobb.collectionService.findAll({
32
+ collectionName: "auth_users",
33
+ params: { filter: { role: "admin" } },
34
+ });
35
+
36
+ expect(result.data[0].role).toEqual("admin");
37
+ });
38
+
39
+ it("should not create a second admin user on re-init", async () => {
40
+ const lobb2 = await Lobb.init(authWithAdminExtraFieldsConfig);
41
+
42
+ const result = await lobb2.collectionService.findAll({
43
+ collectionName: "auth_users",
44
+ params: { filter: { role: "admin" } },
45
+ });
46
+
47
+ expect(result.data.length).toEqual(1);
48
+ await lobb2.close();
49
+ });
50
+ });
@@ -3,12 +3,9 @@ import type { ExtensionConfig } from "../config/extensionConfigSchema.ts";
3
3
  import { getPoliciesWorkflows } from "./policiesWorkflows.ts";
4
4
  import { meAliasWorkflows } from "./meAliasWorkflows.ts";
5
5
  import { baseWorkflows } from "./baseWorkflow.ts";
6
- import { hashHandlerWorkflows } from "./hashHandlerWorkflows.ts";
7
-
8
6
  export function getWorkflows(extensionConfig: ExtensionConfig): Workflow[] {
9
7
  return [
10
8
  ...baseWorkflows,
11
- ...hashHandlerWorkflows,
12
9
 
13
10
  // TODO: think about putting the below workflows above at the beggining
14
11
  // this will give us the ability to specify which roles have the ability to login, register etc
@@ -37,7 +37,7 @@ export function handlePolicy({
37
37
  }
38
38
 
39
39
  const config = extensionConfig;
40
- const currentRole = config.roles[role];
40
+ const currentRole = config.roles?.[role];
41
41
 
42
42
  if (typeof currentRole === "undefined") {
43
43
  throw new ctx.LobbError({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lobb-js/lobb-ext-auth",
3
- "version": "0.3.1",
4
- "license": "AGPL-3.0-only",
3
+ "version": "0.4.1",
4
+ "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -33,12 +33,12 @@
33
33
  "package": "svelte-package --input extensions/auth/studio"
34
34
  },
35
35
  "dependencies": {
36
- "@lobb-js/core": "^0.14.0",
36
+ "@lobb-js/core": "^0.21.0",
37
37
  "argon2": "^0.40.3",
38
38
  "hono": "^4.7.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@lobb-js/studio": "^0.8.1",
41
+ "@lobb-js/studio": "^0.15.0",
42
42
  "@lucide/svelte": "^0.563.1",
43
43
  "@playwright/test": "^1.58.2",
44
44
  "@sveltejs/adapter-node": "^5.5.4",
@@ -1,29 +0,0 @@
1
- import type { Workflow } from "@lobb-js/core";
2
- import { hash } from "argon2";
3
-
4
- export const hashHandlerWorkflows: Workflow[] = [
5
- // hash passwords on user create
6
- {
7
- name: "auth_hashPasswordWorkflow",
8
- eventName: "core.store.preCreateOne",
9
- handler: async (input) => {
10
- if (input.collectionName === "auth_users") {
11
- input.data.password = await hash(input.data.password);
12
- }
13
- return input;
14
- },
15
- },
16
- // hash passwords on user update
17
- {
18
- name: "auth_hashPasswordWorkflowForUpdate",
19
- eventName: "core.store.preUpdateOne",
20
- handler: async (input) => {
21
- if (input.collectionName === "auth_users") {
22
- if (input.data.password) {
23
- input.data.password = await hash(input.data.password);
24
- }
25
- }
26
- return input;
27
- },
28
- },
29
- ];