@tomei/sso 0.41.0 → 0.42.0

Sign up to get free protection for your applications and to get access to all the features.
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