@tomei/sso 0.41.0 → 0.42.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomei/sso",
3
- "version": "0.41.0",
3
+ "version": "0.42.0",
4
4
  "description": "Tomei SSO Package",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -1780,4 +1780,124 @@ export class Group extends TreeNodeBase<Group> {
1780
1780
  throw error;
1781
1781
  }
1782
1782
  }
1783
+
1784
+ public static async getHierarchy(
1785
+ loginUser: LoginUser,
1786
+ dbTransaction: any,
1787
+ Status?: string,
1788
+ Type?: GroupTypeEnum,
1789
+ ParentGroupCode?: string,
1790
+ ) {
1791
+ // This method retrieves all group records from the sso_Group table in a hierarchical tree structure based on
1792
+ // the ParentGroupCode. The hierarchy respects any filtering options passed, such as status or group type, and
1793
+ // checks privileges of the requesting user.
1794
+
1795
+ // Part 1: Privilege Checking
1796
+ // Call loginUser.checkPrivileges() by passing:
1797
+ // - SystemCode: Retrieved from the system configuration.
1798
+ // - PrivilegeCode: 'GROUP_VIEW'.
1799
+ // Ensure the user has privileges to view group information.
1800
+ const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
1801
+ const isPrivileged = await loginUser.checkPrivileges(
1802
+ systemCode,
1803
+ 'GROUP_VIEW',
1804
+ );
1805
+
1806
+ if (!isPrivileged) {
1807
+ throw new ClassError(
1808
+ 'Group',
1809
+ 'GroupErrMsg04',
1810
+ 'User is not privileged to view group',
1811
+ );
1812
+ }
1813
+
1814
+ // Part 2: Prepare Filters
1815
+ // Set the default filter for Status to "Active", unless specified.
1816
+ // Use optional filters such as Type and ParentGroupCode if provided.
1817
+ const queryObj: any = {};
1818
+
1819
+ let options: any = {
1820
+ transaction: dbTransaction,
1821
+ };
1822
+
1823
+ const search = {
1824
+ Status: Status ? Status : 'Active',
1825
+ Type: Type,
1826
+ ParentGroupCode: ParentGroupCode,
1827
+ };
1828
+
1829
+ if (search) {
1830
+ Object.entries(search).forEach(([key, value]) => {
1831
+ if (value) {
1832
+ queryObj[key] = {
1833
+ [Op.substring]: value,
1834
+ };
1835
+ }
1836
+ });
1837
+
1838
+ options = {
1839
+ ...options,
1840
+ where: queryObj,
1841
+ };
1842
+
1843
+ // Part 3: Retrieve Group Data
1844
+ // Use Sequelize's findAll() method with the provided filters (status, type, and parentGroupCode) to query the sso_Group table.
1845
+ // Recursively build the group tree based on ParentGroupCode relationships.
1846
+
1847
+ const result = await Group._Repo.findAll(options);
1848
+ const data = result.map((group) => new Group(group.get({ plain: true })));
1849
+
1850
+ const generateTree = async (groups) => {
1851
+ // Create a map for easy lookup by code
1852
+
1853
+ const data = groups.map((group) => {
1854
+ return {
1855
+ GroupCode: group.ObjectId,
1856
+ Name: group.Name,
1857
+ Description: group.Description,
1858
+ Type: group.Type,
1859
+ ParentGroupCode: group.ParentGroupCode,
1860
+ InheritParentPrivilegeYN: group.InheritParentPrivilegeYN,
1861
+ InheritParentSystemAccessYN: group.InheritParentSystemAccessYN,
1862
+ Path: group._Path,
1863
+ Status: group.Status,
1864
+ CreatedById: group._CreatedById,
1865
+ CreatedAt: group._CreatedAt,
1866
+ UpdatedById: group._UpdatedById,
1867
+ UpdatedAt: group._UpdatedAt,
1868
+ childrens: [],
1869
+ };
1870
+ });
1871
+ const groupMap = {};
1872
+ data.forEach((group) => {
1873
+ group.childrens = [];
1874
+ groupMap[group.GroupCode] = group;
1875
+ });
1876
+
1877
+ // Initialize the root nodes (those without a parentCode)
1878
+ const tree = [];
1879
+
1880
+ data.forEach((group) => {
1881
+ if (group.ParentGroupCode) {
1882
+ // Add this group as a child of its parent
1883
+ const parent = groupMap[group.ParentGroupCode];
1884
+ if (parent) {
1885
+ parent.childrens.push(group);
1886
+ }
1887
+ } else {
1888
+ // If no parentCode, it's a root node
1889
+ tree.push(group);
1890
+ }
1891
+ });
1892
+
1893
+ return tree;
1894
+ };
1895
+
1896
+ const tree = await generateTree(data);
1897
+
1898
+ // Part 4: Return Results
1899
+ // Return the tree structure with child groups (under the childrens key) included only if a group has child groups.
1900
+ return tree;
1901
+ }
1902
+ }
1783
1903
  }
@@ -1,6 +1,10 @@
1
- import { ClassError, HashTable, ObjectBase } from '@tomei/general';
1
+ import { ClassError, ObjectBase } from '@tomei/general';
2
2
  import { GroupReportingUserRepository } from './group-reporting-user.repository';
3
3
  import { IGroupReportingUserAttr } from '../../interfaces/group-reporting-user.interface';
4
+ import { User } from '../login-user/user';
5
+ import { Group } from '../group/group';
6
+ import { ApplicationConfig } from '@tomei/config';
7
+ import { ActionEnum, Activity } from '@tomei/activity-history';
4
8
 
5
9
  export class GroupReportingUser extends ObjectBase {
6
10
  ObjectId: string;
@@ -78,4 +82,113 @@ export class GroupReportingUser extends ObjectBase {
78
82
  );
79
83
  }
80
84
  }
85
+
86
+ async createGroupReportingUser(
87
+ loginUser: User, //The user performing the operation(typically the logged -in user).
88
+ dbTransaction: any, //Database transaction object to ensure the operation is atomic.
89
+ groupCode: string, //The code of the group to which the user is being assigned.
90
+ userId: number, //The ID of the user to be added to the group.
91
+ rank: number, //The rank to be assigned to the user in the group.
92
+ status: 'Active' | 'Inactive', //The initial status of the user in the group.
93
+ ): Promise<GroupReportingUser> { // Returns a GroupReportingUser instance representing the newly created record.
94
+ try {
95
+ //Creates a new group reporting user entry in the sso_GroupReportingUser table.
96
+
97
+ // Validate Input Parameters
98
+ // Ensure groupCode exists in the sso_Group table by calling the Group.init() method.
99
+ const group = await Group.init(dbTransaction, groupCode);
100
+ // Ensure userId exists in the sso_User table by calling the User.init() method.
101
+ const user = await User.init(dbTransaction, userId);
102
+ // Privilege Checking
103
+ // Call the loginUser.checkPrivileges() method by passing:
104
+ // SystemCode: Retrieve from app config.
105
+ // PrivilegeCode: "GROUP_REPORTING_USER_CREATE".
106
+
107
+ const systemCode =
108
+ ApplicationConfig.getComponentConfigValue('system-code');
109
+ const isPrivileged = await loginUser.checkPrivileges(
110
+ systemCode,
111
+ 'GROUP_REPORTING_USER_CREATE',
112
+ );
113
+ if (!isPrivileged) {
114
+ throw new ClassError(
115
+ 'GroupReportingUser',
116
+ 'GroupReportingUserErrMsg02',
117
+ 'User does not have the privilege to create Group Reporting User',
118
+ );
119
+ }
120
+
121
+ // Check for Duplicate User in Group
122
+ // Query the sso_GroupReportingUser table to see if the userId already exists in the specified groupCode.
123
+ const groupReportingUser = await GroupReportingUser._Repo.findOne({
124
+ where: {
125
+ GroupCode: groupCode,
126
+ UserId: userId,
127
+ },
128
+ transaction: dbTransaction,
129
+ });
130
+ // If the user already exists in the group, throw an error indicating the user is already part of the group.
131
+ if (groupReportingUser) {
132
+ throw new ClassError(
133
+ 'GroupReportingUser',
134
+ 'GroupReportingUserErrMsg03',
135
+ 'User already exists in the group',
136
+ 'createGroupReportingUser',
137
+ );
138
+ }
139
+ // Create GroupReportingUser Entry
140
+ // If validation and privilege checks pass, insert a new record in the sso_GroupReportingUser table with the provided groupCode, userId, rank, status, and loginUser.UserId.Automatically capture the current timestamp for CreatedAt.
141
+ this.GroupCode = groupCode;
142
+ this.UserId = userId;
143
+ this.Rank = rank;
144
+ this.Status = status;
145
+ this._CreatedById = loginUser.UserId;
146
+ this._CreatedAt = new Date();
147
+
148
+ const entityValueAfter: any = {
149
+ GroupCode: groupCode,
150
+ UserId: userId,
151
+ Rank: rank,
152
+ Status: status,
153
+ CreatedById: loginUser.UserId,
154
+ CreatedAt: this._CreatedAt,
155
+ };
156
+
157
+ const newGroupReportingUser = await GroupReportingUser._Repo.create(
158
+ entityValueAfter,
159
+ {
160
+ transaction: dbTransaction,
161
+ },
162
+ );
163
+
164
+ entityValueAfter.GroupReportingUserId =
165
+ newGroupReportingUser.GroupReportingUserId;
166
+
167
+ // Record Create Activity
168
+ // Instantiate a new activity from the Activity class, and set:\
169
+ // ActivityId: activity.createId()
170
+ // Action: ActionEnum.Create
171
+ // Description: Create Group Reporting User
172
+ // EntityType: GroupReportingUser
173
+ // EntityId: newGroupReportingUser.GroupReportingUserId
174
+ // EntityValueBefore: Stringified empty object({})
175
+ // EntityValueAfter: EntityValueAfter(stringified representation of the newly created entity)
176
+ const activity = new Activity();
177
+ activity.Action = ActionEnum.CREATE;
178
+ activity.Description = 'Create Group Reporting User';
179
+ activity.EntityType = 'GroupReportingUser';
180
+ activity.EntityId = newGroupReportingUser.GroupReportingUserId.toString();
181
+ activity.EntityValueBefore = JSON.stringify({});
182
+ activity.EntityValueAfter = JSON.stringify(entityValueAfter);
183
+ // Call the activity create() method by passing:
184
+ // dbTransaction
185
+ // userId: loginUser.UserId
186
+ await activity.create(loginUser.ObjectId, dbTransaction);
187
+ // Return the Created GroupReportingUser
188
+ // Return the newly created GroupReportingUser instance, including all the relevant details like GroupReportingUserId, groupCode, userId, rank, status, and timestamps for CreatedAt.
189
+ return this;
190
+ } catch (error) {
191
+ throw error;
192
+ }
193
+ }
81
194
  }
Binary file