@loomcore/api 0.1.11 → 0.1.13

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.
@@ -10,7 +10,7 @@ import { OrganizationService } from '../services/organization.service.js';
10
10
  import { IdNotFoundError } from '../errors/index.js';
11
11
  import { AuthService, GenericApiService } from '../services/index.js';
12
12
  import { ObjectId } from 'mongodb';
13
- import { testMetaOrg, testOrg, getTestUser, testUserContext } from './test-objects.js';
13
+ import { testMetaOrg, testOrg, getTestMetaOrgUser, testMetaOrgUserContext } from './test-objects.js';
14
14
  import { CategorySpec } from './models/category.model.js';
15
15
  import { ProductSpec } from './models/product.model.js';
16
16
  let deviceIdCookie;
@@ -33,9 +33,9 @@ async function createMetaOrg() {
33
33
  throw new Error('OrganizationService not initialized. Call initialize() first.');
34
34
  }
35
35
  try {
36
- const existingMetaOrg = await organizationService.findOne(testUserContext, { filters: { isMetaOrg: { eq: true } } });
36
+ const existingMetaOrg = await organizationService.findOne(testMetaOrgUserContext, { filters: { isMetaOrg: { eq: true } } });
37
37
  if (!existingMetaOrg) {
38
- const metaOrgInsertResult = await organizationService.create(testUserContext, testMetaOrg);
38
+ const metaOrgInsertResult = await organizationService.create(testMetaOrgUserContext, testMetaOrg);
39
39
  }
40
40
  }
41
41
  catch (error) {
@@ -48,7 +48,7 @@ async function deleteMetaOrg() {
48
48
  return Promise.resolve();
49
49
  }
50
50
  try {
51
- await organizationService.deleteMany(testUserContext, { filters: { isMetaOrg: { eq: true } } });
51
+ await organizationService.deleteMany(testMetaOrgUserContext, { filters: { isMetaOrg: { eq: true } } });
52
52
  }
53
53
  catch (error) {
54
54
  console.log('Error deleting meta org:', error);
@@ -69,23 +69,23 @@ async function createTestUser() {
69
69
  throw new Error('Database not initialized. Call initialize() first.');
70
70
  }
71
71
  try {
72
- let existingOrg;
72
+ let existingMetaOrg;
73
73
  try {
74
- existingOrg = await organizationService.getById(testUserContext, testOrg._id);
74
+ existingMetaOrg = await organizationService.getMetaOrg(testMetaOrgUserContext);
75
75
  }
76
76
  catch (error) {
77
77
  if (error instanceof IdNotFoundError) {
78
- existingOrg = null;
78
+ existingMetaOrg = null;
79
79
  }
80
80
  else {
81
81
  throw error;
82
82
  }
83
83
  }
84
- if (!existingOrg) {
85
- await organizationService.create(testUserContext, testOrg);
84
+ if (!existingMetaOrg) {
85
+ await organizationService.create(testMetaOrgUserContext, testMetaOrg);
86
86
  }
87
87
  const systemUserContext = getSystemUserContext();
88
- const createdUser = await authService.createUser(systemUserContext, getTestUser());
88
+ const createdUser = await authService.createUser(systemUserContext, getTestMetaOrgUser());
89
89
  if (!createdUser) {
90
90
  throw new Error('Failed to create test user');
91
91
  }
@@ -97,10 +97,10 @@ async function createTestUser() {
97
97
  }
98
98
  }
99
99
  async function deleteTestUser() {
100
- await authService.deleteById(testUserContext, getTestUser()._id).catch((error) => {
100
+ await authService.deleteById(testMetaOrgUserContext, getTestMetaOrgUser()._id).catch((error) => {
101
101
  return null;
102
102
  });
103
- await organizationService.deleteById(testUserContext, testOrg._id).catch((error) => {
103
+ await organizationService.deleteById(testMetaOrgUserContext, testOrg._id).catch((error) => {
104
104
  return null;
105
105
  });
106
106
  }
@@ -119,19 +119,20 @@ async function simulateloginWithTestUser() {
119
119
  return res;
120
120
  }
121
121
  };
122
- const loginResponse = await authService.attemptLogin(req, res, getTestUser().email, getTestUser().password);
122
+ const loginResponse = await authService.attemptLogin(req, res, getTestMetaOrgUser().email, getTestMetaOrgUser().password);
123
123
  if (!loginResponse?.tokens?.accessToken) {
124
124
  throw new Error('Failed to login with test user');
125
125
  }
126
126
  return `Bearer ${loginResponse.tokens.accessToken}`;
127
127
  }
128
128
  function getAuthToken() {
129
+ const metaOrgUser = getTestMetaOrgUser();
129
130
  const payload = {
130
131
  user: {
131
- _id: getTestUser()._id,
132
- email: getTestUser().email
132
+ _id: metaOrgUser._id,
133
+ email: metaOrgUser.email
133
134
  },
134
- _orgId: testOrg._id
135
+ _orgId: metaOrgUser._orgId
135
136
  };
136
137
  const token = JwtService.sign(payload, JWT_SECRET, { expiresIn: 3600 });
137
138
  return `Bearer ${token}`;
@@ -226,7 +227,7 @@ function configureJwtSecret() {
226
227
  }
227
228
  async function loginWithTestUser(agent) {
228
229
  agent.set('Cookie', [`deviceId=${deviceIdCookie}`]);
229
- const testUser = getTestUser();
230
+ const testUser = getTestMetaOrgUser();
230
231
  const response = await agent
231
232
  .post('/api/auth/login')
232
233
  .send({
@@ -1,6 +1,6 @@
1
- import { IOrganization, IUser, IUserContext } from "@loomcore/common/models";
2
- export declare const testUser: IUser;
3
- export declare function getTestUser(): {
1
+ import { IOrganization, IUserContext } from "@loomcore/common/models";
2
+ export declare const testMetaOrg: IOrganization;
3
+ export declare function getTestMetaOrgUser(): {
4
4
  email: string;
5
5
  firstName?: string;
6
6
  lastName?: string;
@@ -18,6 +18,24 @@ export declare function getTestUser(): {
18
18
  _id: string;
19
19
  _orgId?: string;
20
20
  };
21
- export declare const testUserContext: IUserContext;
22
- export declare const testMetaOrg: IOrganization;
21
+ export declare const testMetaOrgUserContext: IUserContext;
23
22
  export declare const testOrg: IOrganization;
23
+ export declare function getTestOrgUser(): {
24
+ email: string;
25
+ firstName?: string;
26
+ lastName?: string;
27
+ displayName?: string;
28
+ password: string;
29
+ roles?: string[];
30
+ _lastLoggedIn?: Date;
31
+ _lastPasswordChange?: Date;
32
+ _created: Date;
33
+ _createdBy: string;
34
+ _updated: Date;
35
+ _updatedBy: string;
36
+ _deleted?: Date;
37
+ _deletedBy?: string;
38
+ _id: string;
39
+ _orgId?: string;
40
+ };
41
+ export declare const testOrgUserContext: IUserContext;
@@ -1,4 +1,15 @@
1
- export const testUser = {
1
+ export const testMetaOrg = {
2
+ _id: '69261691f936c45f85da24d0',
3
+ name: 'Test Meta Organization',
4
+ code: 'test-meta-org',
5
+ status: 1,
6
+ isMetaOrg: true,
7
+ _created: new Date(),
8
+ _createdBy: 'system',
9
+ _updated: new Date(),
10
+ _updatedBy: 'system',
11
+ };
12
+ const testMetaOrgUser = {
2
13
  _id: '69261672f48fb7bf76e54dfb',
3
14
  email: 'test@example.com',
4
15
  password: 'testpassword',
@@ -6,7 +17,7 @@ export const testUser = {
6
17
  lastName: 'User',
7
18
  displayName: 'Test User',
8
19
  roles: ['user'],
9
- _orgId: '6926167d06c0073a778a124f',
20
+ _orgId: testMetaOrg._id,
10
21
  _created: new Date(),
11
22
  _createdBy: 'system',
12
23
  _lastLoggedIn: new Date(),
@@ -14,23 +25,12 @@ export const testUser = {
14
25
  _updated: new Date(),
15
26
  _updatedBy: 'system',
16
27
  };
17
- export function getTestUser() {
18
- return { ...testUser };
28
+ export function getTestMetaOrgUser() {
29
+ return { ...testMetaOrgUser };
19
30
  }
20
- export const testUserContext = {
21
- user: getTestUser(),
22
- _orgId: '6926167d06c0073a778a124f'
23
- };
24
- export const testMetaOrg = {
25
- _id: '69261691f936c45f85da24d0',
26
- name: 'Test Meta Organization',
27
- code: 'test-meta-org',
28
- status: 1,
29
- isMetaOrg: true,
30
- _created: new Date(),
31
- _createdBy: 'system',
32
- _updated: new Date(),
33
- _updatedBy: 'system',
31
+ export const testMetaOrgUserContext = {
32
+ user: getTestMetaOrgUser(),
33
+ _orgId: testMetaOrg._id,
34
34
  };
35
35
  export const testOrg = {
36
36
  _id: '6926167d06c0073a778a124f',
@@ -43,3 +43,25 @@ export const testOrg = {
43
43
  _updated: new Date(),
44
44
  _updatedBy: 'system',
45
45
  };
46
+ const testOrgUser = {
47
+ _id: '6926167d06c0073a778a1250',
48
+ email: 'test-org-user@example.com',
49
+ password: 'testpassword',
50
+ firstName: 'Test',
51
+ lastName: 'User',
52
+ displayName: 'Test User',
53
+ roles: ['user'],
54
+ _orgId: testOrg._id,
55
+ _created: new Date(),
56
+ _createdBy: 'system',
57
+ _lastLoggedIn: new Date(),
58
+ _updated: new Date(),
59
+ _updatedBy: 'system',
60
+ };
61
+ export function getTestOrgUser() {
62
+ return { ...testOrgUser };
63
+ }
64
+ export const testOrgUserContext = {
65
+ user: getTestOrgUser(),
66
+ _orgId: testOrg._id,
67
+ };
@@ -13,7 +13,7 @@ export class AuthController {
13
13
  }
14
14
  mapRoutes(app) {
15
15
  app.post(`/api/auth/login`, this.login.bind(this), this.afterAuth.bind(this));
16
- app.post(`/api/auth/register`, this.registerUser.bind(this));
16
+ app.post(`/api/auth/register`, isAuthenticated, this.registerUser.bind(this));
17
17
  app.get(`/api/auth/refresh`, this.requestTokenUsingRefreshToken.bind(this));
18
18
  app.get(`/api/auth/get-user-context`, isAuthenticated, this.getUserContext.bind(this));
19
19
  app.patch(`/api/auth/change-password`, isAuthenticated, this.changePassword.bind(this));
@@ -1,2 +1,3 @@
1
1
  export * from './postgres.database.js';
2
2
  export * from './migrations/index.js';
3
+ export * from './utils/index.js';
@@ -1,2 +1,3 @@
1
1
  export * from './postgres.database.js';
2
2
  export * from './migrations/index.js';
3
+ export * from './utils/index.js';
@@ -0,0 +1 @@
1
+ export * from './does-table-exist.util.js';
@@ -0,0 +1 @@
1
+ export * from './does-table-exist.util.js';
@@ -3,6 +3,7 @@ import { IOrganization, IUserContext } from '@loomcore/common/models';
3
3
  import { IDatabase } from '../databases/models/database.interface.js';
4
4
  export declare class OrganizationService extends GenericApiService<IOrganization> {
5
5
  constructor(database: IDatabase);
6
+ preprocessEntity(userContext: IUserContext, entity: Partial<IOrganization>, isCreate: boolean, allowId?: boolean): Promise<Partial<IOrganization>>;
6
7
  getAuthTokenByRepoCode(userContext: IUserContext, orgId: string): Promise<string | null>;
7
8
  validateRepoAuthToken(userContext: IUserContext, orgCode: string, authToken: string): Promise<string | null>;
8
9
  getMetaOrg(userContext: IUserContext): Promise<IOrganization | null>;
@@ -1,9 +1,23 @@
1
1
  import { GenericApiService } from './generic-api-service/generic-api.service.js';
2
2
  import { OrganizationSpec } from '@loomcore/common/models';
3
+ import { BadRequestError } from '../errors/index.js';
3
4
  export class OrganizationService extends GenericApiService {
4
5
  constructor(database) {
5
6
  super(database, 'organizations', 'organization', OrganizationSpec);
6
7
  }
8
+ async preprocessEntity(userContext, entity, isCreate, allowId = true) {
9
+ if (isCreate) {
10
+ const metaOrg = await this.getMetaOrg(userContext);
11
+ if (metaOrg && entity.isMetaOrg) {
12
+ throw new BadRequestError('Meta organization already exists');
13
+ }
14
+ if (metaOrg && userContext._orgId !== metaOrg._id) {
15
+ throw new BadRequestError('User is not authorized to create an organization');
16
+ }
17
+ }
18
+ const result = await super.preprocessEntity(userContext, entity, isCreate, allowId);
19
+ return result;
20
+ }
7
21
  async getAuthTokenByRepoCode(userContext, orgId) {
8
22
  const org = await this.getById(userContext, orgId);
9
23
  return org?.authToken ?? null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loomcore/api",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "private": false,
5
5
  "description": "Loom Core Api - An opinionated Node.js api using Typescript, Express, and MongoDb or PostgreSQL",
6
6
  "scripts": {