aws-service-stack 0.18.392 → 0.18.394

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.
@@ -137,11 +137,11 @@ class ControllerRole {
137
137
  const roles = this.extractRoles(req);
138
138
  if (!roles.length)
139
139
  this.deny();
140
+ if (adminGroups?.length && this.isAdmin(roles, adminGroups))
141
+ return true;
140
142
  const method = req.methode.toUpperCase();
141
143
  const scope = this.getScope(req, scopeMap);
142
144
  this.applyMethodFilters(req, method, scope, scopeMap);
143
- if (adminGroups?.length && this.isAdmin(roles, adminGroups))
144
- return true;
145
145
  const permitted = await this.hasAnyRolePermission(roles, resource, scope, method);
146
146
  if (!permitted) {
147
147
  this.deny(`Permission denied: ${roles.join(",")}: "${resource}#${scope}.${method}"`);
@@ -163,6 +163,7 @@ class ControllerRole {
163
163
  throw new exception_1.ErrorHttp({ code: 403, error: "PermissionDenied" }, message);
164
164
  }
165
165
  isAdmin(cognitoGroups, adminGroups) {
166
+ adminGroups = (0, string_util_1.normalizeLower)(adminGroups);
166
167
  return cognitoGroups?.some((group) => adminGroups.includes(group)) ?? false;
167
168
  }
168
169
  extractRoles(req) {
@@ -1 +1 @@
1
- {"version":3,"file":"controller-role.js","sourceRoot":"","sources":["../../src/controller/controller-role.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,4CAAyC;AAIzC,sEAAkE;AAClE,iDAAoG;AACpG,8DAA4E;AAC5E,sDAAuD;AAGvD,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E,MAAM,YAAY,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5B,GAAG,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC5B,KAAK,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC7B,GAAG,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC3B,MAAM,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,OAAC,CAAC,MAAM,CAAC;IAChC,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,kBAAkB,CAAC;IAC3C,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,sBAAsB,CAAC;IACnD,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,CAAC;IAC7C,MAAM,EAAE,YAAY;CACrB,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAAG,OAAC,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,QAAQ,EAAE;IACtD,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,QAAQ,EAAE;IAC9D,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,QAAQ,EAAE;IACxD,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;AAEvD,MAAM,QAAQ,GAAG,OAAC,CAAC,MAAM,CAAC;IACxB,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;IACvD,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,uBAAuB,CAAC;IACrD,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACnC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5B,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;IACvD,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,sBAAsB,CAAC;IACnD,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,uBAAuB,CAAC;CACtD,CAAC,CAAC;AAEH,8EAA8E;AAE9E,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;AAI7D,MAAa,cAAc;IACN,iBAAiB,CAAoB;IAEvC,SAAS,GAAiC;QACzD,YAAY,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC;QACzF,iBAAiB,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC;QAC9F,eAAe,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;QAC7E,oBAAoB,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC;KACpG,CAAC;IAEF,YAAY,aAAqB;QAC/B,IAAI,CAAC,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,aAAa,CAAC,CAAC;IAChE,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E,KAAK,CAAC,aAAa,CAAC,KAKnB;QACC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,EAAU,EACV,OAA4E;QAE5E,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,EAAU;QAC/B,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,EAAU;QAC5B,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,MAAe;QACnC,OAAO,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IACxD,CAAC;IAED,8EAA8E;IAC9E,uBAAuB;IACvB,8EAA8E;IAE9E,KAAK,CAAC,OAAO,CAAC,UAAkB,EAAE,SAAiB,EAAE,WAAoB;QACvE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;QAChE,OAAO,IAAA,qBAAW,EAAC,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAkB,EAAE,SAAiB;QACpD,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;QACnD,OAAO,IAAA,qBAAW,EAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAkB,EAAE,QAAgB,EAAE,SAAiB;QACtE,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACjE,OAAO,IAAA,wBAAc,EAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,UAAkB,EAAE,QAAgB,EAAE,SAAiB;QACxE,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACjE,OAAO,IAAA,6BAAmB,EAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC9D,CAAC;IAED,8EAA8E;IAC9E,qBAAqB;IACrB,8EAA8E;IAE9E,KAAK,CAAC,aAAa,CAAC,IAAY,EAAE,QAAgB,EAAE,KAAa,EAAE,MAAc;QAC/E,OAAO,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAC7E,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,aAAqB;QAC5C,OAAO,IAAI,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;IAClE,CAAC;IAED,8EAA8E;IAC9E,yDAAyD;IACzD,8EAA8E;IAE9E,KAAK,CAAC,uBAAuB,CAC3B,GAAgB,EAChB,IAAY,EACZ,aAA4B,EAC5B,WAAqB;QAErB,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAE5D,IAAI,GAAG,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,cAAc,GAAG,IAAA,6BAAe,EAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,IAAA,6BAAe,EAAC,aAAa,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;YAE/D,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC/D,IAAI,cAAc,KAAK,GAAG,QAAQ,GAAG,MAAM,EAAE,EAAE,CAAC;oBAC9C,OAAO,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC;YAED,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QAED,QAAQ,GAAG,CAAC,OAAO,EAAE,CAAC;YACpB,KAAK,KAAK;gBACR,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC1C,KAAK,OAAO;gBACV,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACvD,KAAK,QAAQ;gBACX,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7C;gBACE,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,2BAA2B,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,0BAA0B;IAC1B,8EAA8E;IAE9E,KAAK,CAAC,WAAW,CACf,GAAgB,EAChB,QAAgB,EAChB,QAAkB,EAClB,WAAsB,EACtB,QAAuC;QAEvC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QAE/B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAE3C,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QAEtD,IAAI,WAAW,EAAE,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC;YAAE,OAAO,IAAI,CAAC;QAEzE,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAClF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,sBAAsB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,QAAQ,IAAI,KAAK,IAAI,MAAM,GAAG,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oBAAoB,CAAC,aAAuB,EAAE,WAAqB;QACjE,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,WAAW,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1D,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACjC,CAAC;IAED,8EAA8E;IAC9E,iCAAiC;IACjC,8EAA8E;IAEtE,IAAI,CAAC,OAAO,GAAG,uCAAuC;QAC5D,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,OAAO,CAAC,CAAC;IACzE,CAAC;IAEO,OAAO,CAAC,aAAmC,EAAE,WAAqB;QACxE,OAAO,aAAa,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC;IAC9E,CAAC;IAEO,YAAY,CAAC,GAAgB;QACnC,OAAO,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAC;IACpC,CAAC;IAEO,QAAQ,CAAC,GAAgB,EAAE,QAAkB;QACnD,OAAO,GAAG,CAAC,qBAAqB,EAAE,KAAK,IAAI,GAAG,CAAC,qBAAqB,EAAE,KAAK,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC;IAC/G,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAChC,KAAe,EACf,QAAgB,EAChB,KAAa,EACb,MAAc;QAEd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,MAAM,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC7F,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,QAAQ,CAAsB,MAAS,EAAE,IAAa;QAC5D,IAAI,CAAC;YACH,OAAO,IAAA,oCAAkB,EAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,eAAe,GAAG,IAAA,8BAAY,EAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,eAAe,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,yCAAyC;IACzC,8EAA8E;IAEtE,KAAK,CAAC,oBAAoB,CAChC,GAAgB,EAChB,KAAa,EACb,QAAkB,EAClB,QAAuC;QAEvC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,IAAI,CAAC,4BAA4B,KAAK,GAAG,CAAC,CAAC;QAEjE,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,qBAAqB,CAAC,CAAC;QACjF,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,qBAAqB,GAAG,CAAC,QAAQ,aAAa,CAAC,CAAC;QACxG,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,UAAU,EAAE,CAAC;YAC/C,IAAI,CAAC,IAAI,CAAC,0CAA0C,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,6BAA6B;IAC7B,8EAA8E;IAEtE,YAAY,CAAC,GAAgB,EAAE,OAA8B;QACnE,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1F,CAAC;IAEO,wBAAwB,CAC9B,GAAgB,EAChB,OAA8B,EAC9B,SAAiB;QAEjB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,SAAS,GAAG,SAAS,CAAC;QAC3D,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC;IAC/F,CAAC;IAED,8EAA8E;IAC9E,+BAA+B;IAC/B,8EAA8E;IAEtE,kBAAkB,CAAC,GAAgB,EAAE,MAAc,EAAE,KAAa,EAAE,QAAkB;QAC5F,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;aAAM,IAAI,MAAM,KAAK,KAAK,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACxC,CAAC;aAAM,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,GAAgB,EAAE,KAAa,EAAE,QAAkB;QAC1E,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;QACjC,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAEtC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACnD,IAAI,UAAU,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;YACnD,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,UAAU,CAAC;QAC/C,CAAC;QACD,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEO,qBAAqB,CAAC,GAAgB,EAAE,QAAkB;QAChE,IAAI,CAAC,GAAG,CAAC,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC;QACzE,IAAI,CAAC,mBAAmB,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;IAEO,iBAAiB,CAAC,GAAgB,EAAE,QAAkB;QAC5D,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;QAEjC,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;QACvD,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QAErE,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC5C,IAAI,UAAU,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,GAAG,UAAU;gBAAE,SAAS;YAEpG,MAAM,UAAU,GAAG,IAAI,CAAC,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YAC1E,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,GAAG,cAAc,CAAC;YACrD,IAAI,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;gBACpD,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,UAAU,CAAC;YACnC,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;IAC1B,CAAC;IAEO,mBAAmB,CAAC,GAAgB,EAAE,QAAkB,EAAE,YAAY,GAAG,KAAK;QACpF,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YAC1E,IAAI,UAAU,IAAI,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjF,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,UAAU,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,GAAgB;QACvC,MAAM,IAAI,GAAG,IAAA,6BAAe,EAAC,GAAG,CAAC,KAAK,EAAE,cAAc,EAAE,YAAY,IAAI,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QAChG,OAAO,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IACvC,CAAC;IAEO,qBAAqB,CAAC,GAAgB;QAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,IAAI,GAAG,CAAC,qBAAqB,EAAE,KAAK,IAAI,GAAG,CAAC,qBAAqB,EAAE,KAAK,CAAC;QAC3G,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACnD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACjD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IACpD,CAAC;IAEO,kBAAkB,CAAC,cAAkC,EAAE,QAAkB;QAC/E,IAAI,CAAC,cAAc;YAAE,OAAO,SAAS,CAAC;QACtC,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC5C,IAAI,SAAS,CAAC,WAAW,EAAE,KAAK,cAAc;gBAAE,OAAO,OAAO,CAAC,KAAK,CAAC;QACvE,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,OAAO,CAAC,KAAc;QAC5B,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;IAC/D,CAAC;IAEO,iBAAiB,CAAC,GAAgB,EAAE,QAAkB;QAC5D,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;YACjC,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC/B,OAAO,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7B,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;CACF;AA1VD,wCA0VC","sourcesContent":["import { z } from \"zod\";\nimport { ErrorHttp } from \"../exception\";\nimport { Permission } from \"../model/role.model\";\nimport { List, PermissionMap, ScopeMap } from \"../model/base.model\";\nimport { HttpRequest } from \"../utils/http/http.util\";\nimport { PermissionService } from \"../service/permission.service\";\nimport { createGroup, deleteGroup, addUserToGroup, removeUserFromGroup } from \"../function/cognito\";\nimport { validateWithSchema, formatErrors } from \"../utils/validation.util\";\nimport { trimSpecialChar } from \"../utils/string.util\";\nimport { Filter } from \"@chinggis/types\";\n\n// ---------------------------------------------------------------------------\n// DTO Schemas\n// ---------------------------------------------------------------------------\n\nconst MethodSchema = z.object({\n GET: z.boolean().optional(),\n POST: z.boolean().optional(),\n PATCH: z.boolean().optional(),\n PUT: z.boolean().optional(),\n DELETE: z.boolean().optional(),\n});\n\nconst AddPermissionDto = z.object({\n role: z.string().min(1, \"Role is required\"),\n resource: z.string().min(1, \"Resource is required\"),\n scope: z.string().min(1, \"Scope is required\"),\n method: MethodSchema,\n});\n\nconst UpdatePermissionDto = z.object({\n role: z.string().min(1, \"Role is required\").optional(),\n resource: z.string().min(1, \"Resource is required\").optional(),\n scope: z.string().min(1, \"Scope is required\").optional(),\n method: MethodSchema.optional(),\n});\n\nconst IdParamDto = z.string().min(1, \"Id is required\");\n\nconst GroupDto = z.object({\n userPoolId: z.string().min(1, \"UserPoolId is required\"),\n groupName: z.string().min(1, \"GroupName is required\"),\n description: z.string().optional(),\n});\n\nconst UserGroupDto = z.object({\n userPoolId: z.string().min(1, \"UserPoolId is required\"),\n username: z.string().min(1, \"Username is required\"),\n groupName: z.string().min(1, \"GroupName is required\"),\n});\n\n// ---------------------------------------------------------------------------\n\nconst MUTATING_METHODS = new Set([\"PATCH\", \"PUT\", \"DELETE\"]);\n\ntype RouteHandler = (permissionMap: PermissionMap, body: any) => Promise<any>;\n\nexport class ControllerRole {\n protected readonly permissionService: PermissionService;\n\n private readonly subRoutes: Record<string, RouteHandler> = {\n \"/add-group\": (pm, body) => this.addRole(pm.userPoolId, body.groupName, body.description),\n \"/add-user-group\": (pm, body) => this.assignRole(pm.userPoolId, body.username, body.groupName),\n \"/remove-group\": (pm, body) => this.removeRole(pm.userPoolId, body.groupName),\n \"/remove-user-group\": (pm, body) => this.unassignRole(pm.userPoolId, body.username, body.groupName),\n };\n\n constructor(roleTableName: string) {\n this.permissionService = new PermissionService(roleTableName);\n }\n\n // ---------------------------------------------------------------------------\n // Permission CRUD\n // ---------------------------------------------------------------------------\n\n async addPermission(input: {\n role: string;\n resource: string;\n scope: string;\n method: Permission[\"method\"];\n }): Promise<Permission> {\n this.validate(AddPermissionDto, input);\n return this.permissionService.createPermission(input);\n }\n\n async updatePermission(\n id: string,\n updates: Partial<Pick<Permission, \"role\" | \"resource\" | \"scope\" | \"method\">>,\n ): Promise<Permission> {\n this.validate(IdParamDto, id);\n this.validate(UpdatePermissionDto, updates);\n return this.permissionService.updatePermission(id, updates);\n }\n\n async deletePermission(id: string): Promise<boolean> {\n this.validate(IdParamDto, id);\n return this.permissionService.deletePermission(id);\n }\n\n async getPermission(id: string): Promise<Permission | null> {\n this.validate(IdParamDto, id);\n return this.permissionService.getPermissionById(id);\n }\n\n async listPermissions(filter?: Filter): Promise<List<Partial<Permission>>> {\n return this.permissionService.listPermissions(filter);\n }\n\n // ---------------------------------------------------------------------------\n // Role (Cognito group)\n // ---------------------------------------------------------------------------\n\n async addRole(userPoolId: string, groupName: string, description?: string) {\n this.validate(GroupDto, { userPoolId, groupName, description });\n return createGroup(userPoolId, groupName, description);\n }\n\n async removeRole(userPoolId: string, groupName: string) {\n this.validate(GroupDto, { userPoolId, groupName });\n return deleteGroup(userPoolId, groupName);\n }\n\n async assignRole(userPoolId: string, username: string, groupName: string) {\n this.validate(UserGroupDto, { userPoolId, username, groupName });\n return addUserToGroup(userPoolId, username, groupName);\n }\n\n async unassignRole(userPoolId: string, username: string, groupName: string) {\n this.validate(UserGroupDto, { userPoolId, username, groupName });\n return removeUserFromGroup(userPoolId, username, groupName);\n }\n\n // ---------------------------------------------------------------------------\n // Permission queries\n // ---------------------------------------------------------------------------\n\n async hasPermission(role: string, resource: string, scope: string, method: string): Promise<boolean> {\n return this.permissionService.hasPermission(role, resource, scope, method);\n }\n\n async getPermissionByKey(permissionKey: string): Promise<Permission | null> {\n return this.permissionService.getPermissionByKey(permissionKey);\n }\n\n // ---------------------------------------------------------------------------\n // Permission request handler (routes from ControllerApi)\n // ---------------------------------------------------------------------------\n\n async handlePermissionRequest(\n req: HttpRequest,\n path: string,\n permissionMap: PermissionMap,\n adminGroups: string[],\n ): Promise<any> {\n this.checkAdminPermission(req.identity.groups, adminGroups);\n\n if (req.methode === \"POST\") {\n const normalizedPath = trimSpecialChar(path);\n const rolePath = trimSpecialChar(permissionMap.rolePath ?? \"\");\n\n for (const [suffix, handler] of Object.entries(this.subRoutes)) {\n if (normalizedPath === `${rolePath}${suffix}`) {\n return handler(permissionMap, req.body);\n }\n }\n\n return this.addPermission(req.body);\n }\n\n switch (req.methode) {\n case \"GET\":\n return this.listPermissions(req.filter);\n case \"PATCH\":\n return this.updatePermission(req.entityId, req.body);\n case \"DELETE\":\n return this.deletePermission(req.entityId);\n default:\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"[CORE] unsupported method\");\n }\n }\n\n // ---------------------------------------------------------------------------\n // RBAC access enforcement\n // ---------------------------------------------------------------------------\n\n async checkAccess(\n req: HttpRequest,\n resource: string,\n scopeMap: ScopeMap,\n adminGroups?: string[],\n findById?: (id: string) => Promise<any>,\n ): Promise<boolean> {\n const roles = this.extractRoles(req);\n if (!roles.length) this.deny();\n\n const method = req.methode.toUpperCase();\n const scope = this.getScope(req, scopeMap);\n\n this.applyMethodFilters(req, method, scope, scopeMap);\n\n if (adminGroups?.length && this.isAdmin(roles, adminGroups)) return true;\n\n const permitted = await this.hasAnyRolePermission(roles, resource, scope, method);\n if (!permitted) {\n this.deny(`Permission denied: ${roles.join(\",\")}: \"${resource}#${scope}.${method}\"`);\n }\n\n if (MUTATING_METHODS.has(method)) {\n await this.verifyScopeOwnership(req, scope, scopeMap, findById);\n }\n\n return true;\n }\n\n checkAdminPermission(cognitoGroups: string[], adminGroups: string[]) {\n if (this.isAdmin(cognitoGroups, adminGroups)) return true;\n this.deny(\"Permission Denied\");\n }\n\n // ---------------------------------------------------------------------------\n // Private — error + auth helpers\n // ---------------------------------------------------------------------------\n\n private deny(message = \"Permission denied: no role accessible\"): never {\n throw new ErrorHttp({ code: 403, error: \"PermissionDenied\" }, message);\n }\n\n private isAdmin(cognitoGroups: string[] | undefined, adminGroups: string[]): boolean {\n return cognitoGroups?.some((group) => adminGroups.includes(group)) ?? false;\n }\n\n private extractRoles(req: HttpRequest): string[] {\n return req.identity?.groups ?? [];\n }\n\n private getScope(req: HttpRequest, scopeMap: ScopeMap): string {\n return req.queryStringParameters?.scope || req.customQueryParameters?.scope || scopeMap.keys().next().value!;\n }\n\n private async hasAnyRolePermission(\n roles: string[],\n resource: string,\n scope: string,\n method: string,\n ): Promise<boolean> {\n for (const role of roles) {\n if (await this.permissionService.hasPermission(role, resource, scope, method)) return true;\n }\n return false;\n }\n\n private validate<T extends z.ZodType>(schema: T, data: unknown): z.infer<T> {\n try {\n return validateWithSchema(schema, data);\n } catch (error) {\n const formattedErrors = formatErrors(error);\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, formattedErrors);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — scope ownership verification\n // ---------------------------------------------------------------------------\n\n private async verifyScopeOwnership(\n req: HttpRequest,\n scope: string,\n scopeMap: ScopeMap,\n findById?: (id: string) => Promise<any>,\n ): Promise<void> {\n const mapping = scopeMap.get(scope);\n if (!mapping) return;\n\n const claimValue = this.resolveClaim(req, mapping);\n if (!claimValue) this.deny(`Missing claim for scope \"${scope}\"`);\n\n if (!findById) return;\n\n if (!req.entityId) {\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Missing resource id\");\n }\n\n const entity = await findById(req.entityId);\n if (!entity) {\n throw new ErrorHttp({ code: 404, error: \"NotFound\" }, `Resource with id \"${req.entityId}\" not found`);\n }\n\n if (entity[mapping.filterField] !== claimValue) {\n this.deny(`Scope mismatch: no access to resource \"${req.entityId}\"`);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — claim resolution\n // ---------------------------------------------------------------------------\n\n private resolveClaim(req: HttpRequest, mapping: { claimKey?: string }): string | undefined {\n return req.identity?.[mapping.claimKey] || req.identity?.attributes?.[mapping.claimKey];\n }\n\n private resolveClaimWithFallback(\n req: HttpRequest,\n mapping: { claimKey?: string },\n scopeName: string,\n ): string | undefined {\n const claimKey = mapping.claimKey ?? \"custom:\" + scopeName;\n return req.identity?.[claimKey] || req.identity?.attributes?.[claimKey] || req.identity?.sub;\n }\n\n // ---------------------------------------------------------------------------\n // Private — filter application\n // ---------------------------------------------------------------------------\n\n private applyMethodFilters(req: HttpRequest, method: string, scope: string, scopeMap: ScopeMap): void {\n if (method === \"POST\") {\n this.setDefaultIndexFields(req, scopeMap);\n } else if (method === \"GET\" && this.isOpenSearchPath(req)) {\n this.setDefaultFilters(req, scopeMap);\n } else if (method === \"GET\") {\n this.applyScopeFilter(req, scope, scopeMap);\n }\n }\n\n private applyScopeFilter(req: HttpRequest, scope: string, scopeMap: ScopeMap): void {\n if (!req.filter) req.filter = {};\n this.clearScopeFilters(req, scopeMap);\n\n const mapping = scopeMap.get(scope);\n if (!mapping) return;\n\n const claimValue = this.resolveClaim(req, mapping);\n if (claimValue || !req.filter[mapping.filterField]) {\n req.filter[mapping.filterField] = claimValue;\n }\n delete req.filter.scope;\n }\n\n private setDefaultIndexFields(req: HttpRequest, scopeMap: ScopeMap): void {\n if (!req.body) req.body = {};\n if (this.isUnset(req.body.ownerId)) req.body.ownerId = req.identity?.sub;\n this.applyAllScopeValues(req, scopeMap, true);\n }\n\n private setDefaultFilters(req: HttpRequest, scopeMap: ScopeMap): void {\n if (!req.filter) req.filter = {};\n\n const requestedScope = this.resolveRequestedScope(req);\n const levelLimit = this.getScopeLevelLimit(requestedScope, scopeMap);\n\n for (const [scopeName, mapping] of scopeMap) {\n if (levelLimit !== undefined && mapping.level !== undefined && mapping.level > levelLimit) continue;\n\n const claimValue = this.resolveClaimWithFallback(req, mapping, scopeName);\n const eqField = mapping.filterField + \".keyword__eq\";\n if (claimValue && this.isUnset(req.filter[eqField])) {\n req.filter[eqField] = claimValue;\n }\n }\n\n delete req.filter.scope;\n }\n\n private applyAllScopeValues(req: HttpRequest, scopeMap: ScopeMap, defaultsOnly = false): void {\n for (const [scopeName, mapping] of scopeMap) {\n const claimValue = this.resolveClaimWithFallback(req, mapping, scopeName);\n if (claimValue && (!defaultsOnly || this.isUnset(req.body[mapping.filterField]))) {\n req.body[mapping.filterField] = claimValue;\n }\n }\n }\n\n private isOpenSearchPath(req: HttpRequest): boolean {\n const path = trimSpecialChar(req.event?.requestContext?.resourcePath ?? req.resourcePath ?? \"\");\n return path.endsWith(\"search/query\");\n }\n\n private resolveRequestedScope(req: HttpRequest): string | undefined {\n const scopeRaw = req.filter?.scope || req.queryStringParameters?.scope || req.customQueryParameters?.scope;\n if (typeof scopeRaw !== \"string\") return undefined;\n const normalized = scopeRaw.trim().toLowerCase();\n return normalized.length ? normalized : undefined;\n }\n\n private getScopeLevelLimit(requestedScope: string | undefined, scopeMap: ScopeMap): number | undefined {\n if (!requestedScope) return undefined;\n for (const [scopeName, mapping] of scopeMap) {\n if (scopeName.toLowerCase() === requestedScope) return mapping.level;\n }\n return undefined;\n }\n\n private isUnset(value: unknown): boolean {\n return value === undefined || value === null || value === \"\";\n }\n\n private clearScopeFilters(req: HttpRequest, scopeMap: ScopeMap): void {\n for (const [, entry] of scopeMap) {\n delete req.filter[entry.filterField];\n }\n delete req.filter[\"profileId\"];\n delete req.filter[\"ownerId\"];\n delete req.filter[\"scope\"];\n }\n}\n"]}
1
+ {"version":3,"file":"controller-role.js","sourceRoot":"","sources":["../../src/controller/controller-role.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { ErrorHttp } from \"../exception\";\nimport { Permission } from \"../model/role.model\";\nimport { List, PermissionMap, ScopeMap } from \"../model/base.model\";\nimport { HttpRequest } from \"../utils/http/http.util\";\nimport { PermissionService } from \"../service/permission.service\";\nimport { createGroup, deleteGroup, addUserToGroup, removeUserFromGroup } from \"../function/cognito\";\nimport { validateWithSchema, formatErrors } from \"../utils/validation.util\";\nimport { normalizeLower, trimSpecialChar } from \"../utils/string.util\";\nimport { Filter } from \"@chinggis/types\";\n\n// ---------------------------------------------------------------------------\n// DTO Schemas\n// ---------------------------------------------------------------------------\n\nconst MethodSchema = z.object({\n GET: z.boolean().optional(),\n POST: z.boolean().optional(),\n PATCH: z.boolean().optional(),\n PUT: z.boolean().optional(),\n DELETE: z.boolean().optional(),\n});\n\nconst AddPermissionDto = z.object({\n role: z.string().min(1, \"Role is required\"),\n resource: z.string().min(1, \"Resource is required\"),\n scope: z.string().min(1, \"Scope is required\"),\n method: MethodSchema,\n});\n\nconst UpdatePermissionDto = z.object({\n role: z.string().min(1, \"Role is required\").optional(),\n resource: z.string().min(1, \"Resource is required\").optional(),\n scope: z.string().min(1, \"Scope is required\").optional(),\n method: MethodSchema.optional(),\n});\n\nconst IdParamDto = z.string().min(1, \"Id is required\");\n\nconst GroupDto = z.object({\n userPoolId: z.string().min(1, \"UserPoolId is required\"),\n groupName: z.string().min(1, \"GroupName is required\"),\n description: z.string().optional(),\n});\n\nconst UserGroupDto = z.object({\n userPoolId: z.string().min(1, \"UserPoolId is required\"),\n username: z.string().min(1, \"Username is required\"),\n groupName: z.string().min(1, \"GroupName is required\"),\n});\n\n// ---------------------------------------------------------------------------\n\nconst MUTATING_METHODS = new Set([\"PATCH\", \"PUT\", \"DELETE\"]);\n\ntype RouteHandler = (permissionMap: PermissionMap, body: any) => Promise<any>;\n\nexport class ControllerRole {\n protected readonly permissionService: PermissionService;\n\n private readonly subRoutes: Record<string, RouteHandler> = {\n \"/add-group\": (pm, body) => this.addRole(pm.userPoolId, body.groupName, body.description),\n \"/add-user-group\": (pm, body) => this.assignRole(pm.userPoolId, body.username, body.groupName),\n \"/remove-group\": (pm, body) => this.removeRole(pm.userPoolId, body.groupName),\n \"/remove-user-group\": (pm, body) => this.unassignRole(pm.userPoolId, body.username, body.groupName),\n };\n\n constructor(roleTableName: string) {\n this.permissionService = new PermissionService(roleTableName);\n }\n\n // ---------------------------------------------------------------------------\n // Permission CRUD\n // ---------------------------------------------------------------------------\n\n async addPermission(input: {\n role: string;\n resource: string;\n scope: string;\n method: Permission[\"method\"];\n }): Promise<Permission> {\n this.validate(AddPermissionDto, input);\n return this.permissionService.createPermission(input);\n }\n\n async updatePermission(\n id: string,\n updates: Partial<Pick<Permission, \"role\" | \"resource\" | \"scope\" | \"method\">>,\n ): Promise<Permission> {\n this.validate(IdParamDto, id);\n this.validate(UpdatePermissionDto, updates);\n return this.permissionService.updatePermission(id, updates);\n }\n\n async deletePermission(id: string): Promise<boolean> {\n this.validate(IdParamDto, id);\n return this.permissionService.deletePermission(id);\n }\n\n async getPermission(id: string): Promise<Permission | null> {\n this.validate(IdParamDto, id);\n return this.permissionService.getPermissionById(id);\n }\n\n async listPermissions(filter?: Filter): Promise<List<Partial<Permission>>> {\n return this.permissionService.listPermissions(filter);\n }\n\n // ---------------------------------------------------------------------------\n // Role (Cognito group)\n // ---------------------------------------------------------------------------\n\n async addRole(userPoolId: string, groupName: string, description?: string) {\n this.validate(GroupDto, { userPoolId, groupName, description });\n return createGroup(userPoolId, groupName, description);\n }\n\n async removeRole(userPoolId: string, groupName: string) {\n this.validate(GroupDto, { userPoolId, groupName });\n return deleteGroup(userPoolId, groupName);\n }\n\n async assignRole(userPoolId: string, username: string, groupName: string) {\n this.validate(UserGroupDto, { userPoolId, username, groupName });\n return addUserToGroup(userPoolId, username, groupName);\n }\n\n async unassignRole(userPoolId: string, username: string, groupName: string) {\n this.validate(UserGroupDto, { userPoolId, username, groupName });\n return removeUserFromGroup(userPoolId, username, groupName);\n }\n\n // ---------------------------------------------------------------------------\n // Permission queries\n // ---------------------------------------------------------------------------\n\n async hasPermission(role: string, resource: string, scope: string, method: string): Promise<boolean> {\n return this.permissionService.hasPermission(role, resource, scope, method);\n }\n\n async getPermissionByKey(permissionKey: string): Promise<Permission | null> {\n return this.permissionService.getPermissionByKey(permissionKey);\n }\n\n // ---------------------------------------------------------------------------\n // Permission request handler (routes from ControllerApi)\n // ---------------------------------------------------------------------------\n\n async handlePermissionRequest(\n req: HttpRequest,\n path: string,\n permissionMap: PermissionMap,\n adminGroups: string[],\n ): Promise<any> {\n this.checkAdminPermission(req.identity.groups, adminGroups);\n\n if (req.methode === \"POST\") {\n const normalizedPath = trimSpecialChar(path);\n const rolePath = trimSpecialChar(permissionMap.rolePath ?? \"\");\n\n for (const [suffix, handler] of Object.entries(this.subRoutes)) {\n if (normalizedPath === `${rolePath}${suffix}`) {\n return handler(permissionMap, req.body);\n }\n }\n\n return this.addPermission(req.body);\n }\n\n switch (req.methode) {\n case \"GET\":\n return this.listPermissions(req.filter);\n case \"PATCH\":\n return this.updatePermission(req.entityId, req.body);\n case \"DELETE\":\n return this.deletePermission(req.entityId);\n default:\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"[CORE] unsupported method\");\n }\n }\n\n // ---------------------------------------------------------------------------\n // RBAC access enforcement\n // ---------------------------------------------------------------------------\n\n async checkAccess(\n req: HttpRequest,\n resource: string,\n scopeMap: ScopeMap,\n adminGroups?: string[],\n findById?: (id: string) => Promise<any>,\n ): Promise<boolean> {\n const roles = this.extractRoles(req);\n if (!roles.length) this.deny();\n\n if (adminGroups?.length && this.isAdmin(roles, adminGroups)) return true;\n\n const method = req.methode.toUpperCase();\n const scope = this.getScope(req, scopeMap);\n\n this.applyMethodFilters(req, method, scope, scopeMap);\n\n const permitted = await this.hasAnyRolePermission(roles, resource, scope, method);\n if (!permitted) {\n this.deny(`Permission denied: ${roles.join(\",\")}: \"${resource}#${scope}.${method}\"`);\n }\n\n if (MUTATING_METHODS.has(method)) {\n await this.verifyScopeOwnership(req, scope, scopeMap, findById);\n }\n\n return true;\n }\n\n checkAdminPermission(cognitoGroups: string[], adminGroups: string[]) {\n if (this.isAdmin(cognitoGroups, adminGroups)) return true;\n this.deny(\"Permission Denied\");\n }\n\n // ---------------------------------------------------------------------------\n // Private — error + auth helpers\n // ---------------------------------------------------------------------------\n\n private deny(message = \"Permission denied: no role accessible\"): never {\n throw new ErrorHttp({ code: 403, error: \"PermissionDenied\" }, message);\n }\n\n private isAdmin(cognitoGroups: string[] | undefined, adminGroups: string[]): boolean {\n adminGroups = normalizeLower(adminGroups);\n return cognitoGroups?.some((group) => adminGroups.includes(group)) ?? false;\n }\n\n private extractRoles(req: HttpRequest): string[] {\n return req.identity?.groups ?? [];\n }\n\n private getScope(req: HttpRequest, scopeMap: ScopeMap): string {\n return req.queryStringParameters?.scope || req.customQueryParameters?.scope || scopeMap.keys().next().value!;\n }\n\n private async hasAnyRolePermission(\n roles: string[],\n resource: string,\n scope: string,\n method: string,\n ): Promise<boolean> {\n for (const role of roles) {\n if (await this.permissionService.hasPermission(role, resource, scope, method)) return true;\n }\n return false;\n }\n\n private validate<T extends z.ZodType>(schema: T, data: unknown): z.infer<T> {\n try {\n return validateWithSchema(schema, data);\n } catch (error) {\n const formattedErrors = formatErrors(error);\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, formattedErrors);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — scope ownership verification\n // ---------------------------------------------------------------------------\n\n private async verifyScopeOwnership(\n req: HttpRequest,\n scope: string,\n scopeMap: ScopeMap,\n findById?: (id: string) => Promise<any>,\n ): Promise<void> {\n const mapping = scopeMap.get(scope);\n if (!mapping) return;\n\n const claimValue = this.resolveClaim(req, mapping);\n if (!claimValue) this.deny(`Missing claim for scope \"${scope}\"`);\n\n if (!findById) return;\n\n if (!req.entityId) {\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Missing resource id\");\n }\n\n const entity = await findById(req.entityId);\n if (!entity) {\n throw new ErrorHttp({ code: 404, error: \"NotFound\" }, `Resource with id \"${req.entityId}\" not found`);\n }\n\n if (entity[mapping.filterField] !== claimValue) {\n this.deny(`Scope mismatch: no access to resource \"${req.entityId}\"`);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private — claim resolution\n // ---------------------------------------------------------------------------\n\n private resolveClaim(req: HttpRequest, mapping: { claimKey?: string }): string | undefined {\n return req.identity?.[mapping.claimKey] || req.identity?.attributes?.[mapping.claimKey];\n }\n\n private resolveClaimWithFallback(\n req: HttpRequest,\n mapping: { claimKey?: string },\n scopeName: string,\n ): string | undefined {\n const claimKey = mapping.claimKey ?? \"custom:\" + scopeName;\n return req.identity?.[claimKey] || req.identity?.attributes?.[claimKey] || req.identity?.sub;\n }\n\n // ---------------------------------------------------------------------------\n // Private — filter application\n // ---------------------------------------------------------------------------\n\n private applyMethodFilters(req: HttpRequest, method: string, scope: string, scopeMap: ScopeMap): void {\n if (method === \"POST\") {\n this.setDefaultIndexFields(req, scopeMap);\n } else if (method === \"GET\" && this.isOpenSearchPath(req)) {\n this.setDefaultFilters(req, scopeMap);\n } else if (method === \"GET\") {\n this.applyScopeFilter(req, scope, scopeMap);\n }\n }\n\n private applyScopeFilter(req: HttpRequest, scope: string, scopeMap: ScopeMap): void {\n if (!req.filter) req.filter = {};\n this.clearScopeFilters(req, scopeMap);\n\n const mapping = scopeMap.get(scope);\n if (!mapping) return;\n\n const claimValue = this.resolveClaim(req, mapping);\n if (claimValue || !req.filter[mapping.filterField]) {\n req.filter[mapping.filterField] = claimValue;\n }\n delete req.filter.scope;\n }\n\n private setDefaultIndexFields(req: HttpRequest, scopeMap: ScopeMap): void {\n if (!req.body) req.body = {};\n if (this.isUnset(req.body.ownerId)) req.body.ownerId = req.identity?.sub;\n this.applyAllScopeValues(req, scopeMap, true);\n }\n\n private setDefaultFilters(req: HttpRequest, scopeMap: ScopeMap): void {\n if (!req.filter) req.filter = {};\n\n const requestedScope = this.resolveRequestedScope(req);\n const levelLimit = this.getScopeLevelLimit(requestedScope, scopeMap);\n\n for (const [scopeName, mapping] of scopeMap) {\n if (levelLimit !== undefined && mapping.level !== undefined && mapping.level > levelLimit) continue;\n\n const claimValue = this.resolveClaimWithFallback(req, mapping, scopeName);\n const eqField = mapping.filterField + \".keyword__eq\";\n if (claimValue && this.isUnset(req.filter[eqField])) {\n req.filter[eqField] = claimValue;\n }\n }\n\n delete req.filter.scope;\n }\n\n private applyAllScopeValues(req: HttpRequest, scopeMap: ScopeMap, defaultsOnly = false): void {\n for (const [scopeName, mapping] of scopeMap) {\n const claimValue = this.resolveClaimWithFallback(req, mapping, scopeName);\n if (claimValue && (!defaultsOnly || this.isUnset(req.body[mapping.filterField]))) {\n req.body[mapping.filterField] = claimValue;\n }\n }\n }\n\n private isOpenSearchPath(req: HttpRequest): boolean {\n const path = trimSpecialChar(req.event?.requestContext?.resourcePath ?? req.resourcePath ?? \"\");\n return path.endsWith(\"search/query\");\n }\n\n private resolveRequestedScope(req: HttpRequest): string | undefined {\n const scopeRaw = req.filter?.scope || req.queryStringParameters?.scope || req.customQueryParameters?.scope;\n if (typeof scopeRaw !== \"string\") return undefined;\n const normalized = scopeRaw.trim().toLowerCase();\n return normalized.length ? normalized : undefined;\n }\n\n private getScopeLevelLimit(requestedScope: string | undefined, scopeMap: ScopeMap): number | undefined {\n if (!requestedScope) return undefined;\n for (const [scopeName, mapping] of scopeMap) {\n if (scopeName.toLowerCase() === requestedScope) return mapping.level;\n }\n return undefined;\n }\n\n private isUnset(value: unknown): boolean {\n return value === undefined || value === null || value === \"\";\n }\n\n private clearScopeFilters(req: HttpRequest, scopeMap: ScopeMap): void {\n for (const [, entry] of scopeMap) {\n delete req.filter[entry.filterField];\n }\n delete req.filter[\"profileId\"];\n delete req.filter[\"ownerId\"];\n delete req.filter[\"scope\"];\n }\n}\n"]}
@@ -50,7 +50,7 @@ class PermissionService {
50
50
  async hasPermission(role, resource, scope, method) {
51
51
  if (!role || !resource || !scope || !method)
52
52
  return false;
53
- const permissionKey = `${role}#${resource}#${scope}`;
53
+ const permissionKey = `${role}.${resource}.${scope}.${method}`;
54
54
  const permission = await this.getPermissionByKey(permissionKey);
55
55
  if (!permission?.method)
56
56
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"permission.service.js","sourceRoot":"","sources":["../../src/service/permission.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Permission } from \"../model/role.model\";\nimport { ErrorHttp } from \"../exception\";\nimport { PermissionCache } from \"./permission.cache\";\nimport { PermissionRepo } from \"./permission.repo\";\nimport { Filter, List } from \"@chinggis/types\";\n\n/**\n * PermissionService — cache + orchestration layer for Permission entities.\n *\n * Design decisions:\n * - Read-through cache via PermissionCache (in-flight dedup, TTL).\n * - Repository handles only DB I/O.\n * - Cache invalidation on every mutation.\n * - ~100 roles total, read-heavy → caching makes sense.\n * - Cache keyed by `perm:{permissionKey}` for deterministic, namespaced lookup.\n */\nexport class PermissionService {\n private readonly repo: PermissionRepo;\n private readonly cache: PermissionCache;\n\n constructor(tableName: string, cacheTtlMs?: number) {\n this.repo = new PermissionRepo(tableName);\n this.cache = new PermissionCache(cacheTtlMs);\n }\n\n // ---------------------------------------------------------------------------\n // Core lookup\n // ---------------------------------------------------------------------------\n\n /** Fetch Permission by composite key (role#resource#scope). Read-through cached. */\n async getPermissionByKey(permissionKey: string): Promise<Permission | null> {\n if (!permissionKey) return null;\n\n return this.cache.getOrFetch(`perm:${permissionKey}`, () => this.repo.findByPermissionKey(permissionKey));\n }\n\n /** Fetch Permission by id. Read-through cached. */\n async getPermissionById(id: string): Promise<Permission | null> {\n if (!id) return null;\n\n return this.cache.getOrFetch(`id:${id}`, () => this.repo.findById(id));\n }\n\n // ---------------------------------------------------------------------------\n // Permission check\n // ---------------------------------------------------------------------------\n\n /**\n * Check if the given role+resource+scope has a specific HTTP method allowed.\n *\n * Builds the permissionKey `role#resource#scope`, fetches the Permission,\n * and checks the method map.\n *\n * @returns `true` if allowed, `false` otherwise.\n */\n async hasPermission(role: string, resource: string, scope: string, method: string): Promise<boolean> {\n if (!role || !resource || !scope || !method) return false;\n\n const permissionKey = `${role}#${resource}#${scope}`;\n const permission = await this.getPermissionByKey(permissionKey);\n if (!permission?.method) return false;\n\n const methodLower = method.toUpperCase() as keyof Permission[\"method\"];\n\n return permission.method[methodLower] === true;\n }\n\n // ---------------------------------------------------------------------------\n // CRUD — create\n // ---------------------------------------------------------------------------\n\n async createPermission(input: {\n role: string;\n resource: string;\n scope: string;\n method: Permission[\"method\"];\n }): Promise<Permission> {\n if (!input.role?.trim()) {\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Role is required\");\n }\n if (!input.resource?.trim()) {\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Resource is required\");\n }\n if (!input.scope?.trim()) {\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Scope is required\");\n }\n\n // Duplicate check\n const permissionKey = `${input.role}#${input.resource}#${input.scope}`;\n const existing = await this.repo.findByPermissionKey(permissionKey);\n if (existing) {\n throw new ErrorHttp({ code: 409, error: \"Conflict\" }, `Permission \"${permissionKey}\" already exists`);\n }\n\n const saved = await this.repo.save({\n role: input.role.trim(),\n resource: input.resource.trim(),\n scope: input.scope.trim(),\n method: input.method ?? {},\n permissionKey,\n });\n\n this.cache.clear();\n return saved;\n }\n\n // ---------------------------------------------------------------------------\n // CRUD — update\n // ---------------------------------------------------------------------------\n\n async updatePermission(\n id: string,\n updates: Partial<Pick<Permission, \"role\" | \"resource\" | \"scope\" | \"method\">>,\n ): Promise<Permission> {\n if (!id) throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Permission id is required\");\n\n const existing = await this.repo.findById(id);\n if (!existing) throw new ErrorHttp({ code: 404, error: \"NotFound\" }, `Permission \"${id}\" not found`);\n\n const data: Partial<Permission> = { id };\n if (updates.role !== undefined) data.role = updates.role.trim();\n if (updates.resource !== undefined) data.resource = updates.resource.trim();\n if (updates.scope !== undefined) data.scope = updates.scope.trim();\n if (updates.method !== undefined) data.method = updates.method;\n\n // Rebuild key if any key component changed\n const role = data.role ?? existing.role;\n const resource = data.resource ?? existing.resource;\n const scope = data.scope ?? existing.scope;\n data.permissionKey = `${role}#${resource}#${scope}`;\n\n // Check for duplicate key if components changed\n if (data.permissionKey !== existing.permissionKey) {\n const conflict = await this.repo.findByPermissionKey(data.permissionKey);\n if (conflict) {\n throw new ErrorHttp({ code: 409, error: \"Conflict\" }, `Permission \"${data.permissionKey}\" already exists`);\n }\n }\n\n const updated = await this.repo.update(data);\n\n this.cache.clear();\n return updated;\n }\n\n // ---------------------------------------------------------------------------\n // CRUD — delete\n // ---------------------------------------------------------------------------\n\n async deletePermission(id: string): Promise<boolean> {\n if (!id) throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Permission id is required\");\n\n const existing = await this.repo.findById(id);\n if (!existing) throw new ErrorHttp({ code: 404, error: \"NotFound\" }, `Permission \"${id}\" not found`);\n\n const result = await this.repo.delete(id);\n\n this.cache.clear();\n return result;\n }\n\n // ---------------------------------------------------------------------------\n // CRUD — list\n // ---------------------------------------------------------------------------\n\n async listPermissions(filter?: Filter): Promise<List<Partial<Permission>>> {\n return this.repo.findByIndex(filter);\n }\n\n // ---------------------------------------------------------------------------\n // Cache control (for testing)\n // ---------------------------------------------------------------------------\n\n clearCache(): void {\n this.cache.clear();\n }\n}\n"]}
1
+ {"version":3,"file":"permission.service.js","sourceRoot":"","sources":["../../src/service/permission.service.ts"],"names":[],"mappings":";;;AACA,4CAAyC;AACzC,yDAAqD;AACrD,uDAAmD;AAGnD;;;;;;;;;GASG;AACH,MAAa,iBAAiB;IACX,IAAI,CAAiB;IACrB,KAAK,CAAkB;IAExC,YAAY,SAAiB,EAAE,UAAmB;QAChD,IAAI,CAAC,IAAI,GAAG,IAAI,gCAAc,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,GAAG,IAAI,kCAAe,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAE9E,oFAAoF;IACpF,KAAK,CAAC,kBAAkB,CAAC,aAAqB;QAC5C,IAAI,CAAC,aAAa;YAAE,OAAO,IAAI,CAAC;QAEhC,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,aAAa,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC;IAC5G,CAAC;IAED,mDAAmD;IACnD,KAAK,CAAC,iBAAiB,CAAC,EAAU;QAChC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAErB,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,8EAA8E;IAC9E,mBAAmB;IACnB,8EAA8E;IAE9E;;;;;;;OAOG;IACH,KAAK,CAAC,aAAa,CAAC,IAAY,EAAE,QAAgB,EAAE,KAAa,EAAE,MAAc;QAC/E,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAE1D,MAAM,aAAa,GAAG,GAAG,IAAI,IAAI,QAAQ,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;QAC/D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;QAChE,IAAI,CAAC,UAAU,EAAE,MAAM;YAAE,OAAO,KAAK,CAAC;QAEtC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,EAAgC,CAAC;QAEvE,OAAO,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACjD,CAAC;IAED,8EAA8E;IAC9E,gBAAgB;IAChB,8EAA8E;IAE9E,KAAK,CAAC,gBAAgB,CAAC,KAKtB;QACC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,kBAAkB,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,sBAAsB,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,mBAAmB,CAAC,CAAC;QAC/E,CAAC;QAED,kBAAkB;QAClB,MAAM,aAAa,GAAG,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QACvE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;QACpE,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,eAAe,aAAa,kBAAkB,CAAC,CAAC;QACxG,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACjC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;YACvB,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE;YAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;YACzB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;YAC1B,aAAa;SACd,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,8EAA8E;IAC9E,gBAAgB;IAChB,8EAA8E;IAE9E,KAAK,CAAC,gBAAgB,CACpB,EAAU,EACV,OAA4E;QAE5E,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,2BAA2B,CAAC,CAAC;QAE9F,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;QAErG,MAAM,IAAI,GAAwB,EAAE,EAAE,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS;YAAE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC5E,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACnE,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAE/D,2CAA2C;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC;QAC3C,IAAI,CAAC,aAAa,GAAG,GAAG,IAAI,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;QAEpD,gDAAgD;QAChD,IAAI,IAAI,CAAC,aAAa,KAAK,QAAQ,CAAC,aAAa,EAAE,CAAC;YAClD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACzE,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,eAAe,IAAI,CAAC,aAAa,kBAAkB,CAAC,CAAC;YAC7G,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE7C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,8EAA8E;IAC9E,gBAAgB;IAChB,8EAA8E;IAE9E,KAAK,CAAC,gBAAgB,CAAC,EAAU;QAC/B,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,2BAA2B,CAAC,CAAC;QAE9F,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,qBAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;QAErG,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAE1C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,8EAA8E;IAC9E,cAAc;IACd,8EAA8E;IAE9E,KAAK,CAAC,eAAe,CAAC,MAAe;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,8EAA8E;IAC9E,8BAA8B;IAC9B,8EAA8E;IAE9E,UAAU;QACR,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF;AAhKD,8CAgKC","sourcesContent":["import { Permission } from \"../model/role.model\";\nimport { ErrorHttp } from \"../exception\";\nimport { PermissionCache } from \"./permission.cache\";\nimport { PermissionRepo } from \"./permission.repo\";\nimport { Filter, List } from \"@chinggis/types\";\n\n/**\n * PermissionService — cache + orchestration layer for Permission entities.\n *\n * Design decisions:\n * - Read-through cache via PermissionCache (in-flight dedup, TTL).\n * - Repository handles only DB I/O.\n * - Cache invalidation on every mutation.\n * - ~100 roles total, read-heavy → caching makes sense.\n * - Cache keyed by `perm:{permissionKey}` for deterministic, namespaced lookup.\n */\nexport class PermissionService {\n private readonly repo: PermissionRepo;\n private readonly cache: PermissionCache;\n\n constructor(tableName: string, cacheTtlMs?: number) {\n this.repo = new PermissionRepo(tableName);\n this.cache = new PermissionCache(cacheTtlMs);\n }\n\n // ---------------------------------------------------------------------------\n // Core lookup\n // ---------------------------------------------------------------------------\n\n /** Fetch Permission by composite key (role#resource#scope). Read-through cached. */\n async getPermissionByKey(permissionKey: string): Promise<Permission | null> {\n if (!permissionKey) return null;\n\n return this.cache.getOrFetch(`perm:${permissionKey}`, () => this.repo.findByPermissionKey(permissionKey));\n }\n\n /** Fetch Permission by id. Read-through cached. */\n async getPermissionById(id: string): Promise<Permission | null> {\n if (!id) return null;\n\n return this.cache.getOrFetch(`id:${id}`, () => this.repo.findById(id));\n }\n\n // ---------------------------------------------------------------------------\n // Permission check\n // ---------------------------------------------------------------------------\n\n /**\n * Check if the given role+resource+scope has a specific HTTP method allowed.\n *\n * Builds the permissionKey `role#resource#scope`, fetches the Permission,\n * and checks the method map.\n *\n * @returns `true` if allowed, `false` otherwise.\n */\n async hasPermission(role: string, resource: string, scope: string, method: string): Promise<boolean> {\n if (!role || !resource || !scope || !method) return false;\n\n const permissionKey = `${role}.${resource}.${scope}.${method}`;\n const permission = await this.getPermissionByKey(permissionKey);\n if (!permission?.method) return false;\n\n const methodLower = method.toUpperCase() as keyof Permission[\"method\"];\n\n return permission.method[methodLower] === true;\n }\n\n // ---------------------------------------------------------------------------\n // CRUD — create\n // ---------------------------------------------------------------------------\n\n async createPermission(input: {\n role: string;\n resource: string;\n scope: string;\n method: Permission[\"method\"];\n }): Promise<Permission> {\n if (!input.role?.trim()) {\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Role is required\");\n }\n if (!input.resource?.trim()) {\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Resource is required\");\n }\n if (!input.scope?.trim()) {\n throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Scope is required\");\n }\n\n // Duplicate check\n const permissionKey = `${input.role}#${input.resource}#${input.scope}`;\n const existing = await this.repo.findByPermissionKey(permissionKey);\n if (existing) {\n throw new ErrorHttp({ code: 409, error: \"Conflict\" }, `Permission \"${permissionKey}\" already exists`);\n }\n\n const saved = await this.repo.save({\n role: input.role.trim(),\n resource: input.resource.trim(),\n scope: input.scope.trim(),\n method: input.method ?? {},\n permissionKey,\n });\n\n this.cache.clear();\n return saved;\n }\n\n // ---------------------------------------------------------------------------\n // CRUD — update\n // ---------------------------------------------------------------------------\n\n async updatePermission(\n id: string,\n updates: Partial<Pick<Permission, \"role\" | \"resource\" | \"scope\" | \"method\">>,\n ): Promise<Permission> {\n if (!id) throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Permission id is required\");\n\n const existing = await this.repo.findById(id);\n if (!existing) throw new ErrorHttp({ code: 404, error: \"NotFound\" }, `Permission \"${id}\" not found`);\n\n const data: Partial<Permission> = { id };\n if (updates.role !== undefined) data.role = updates.role.trim();\n if (updates.resource !== undefined) data.resource = updates.resource.trim();\n if (updates.scope !== undefined) data.scope = updates.scope.trim();\n if (updates.method !== undefined) data.method = updates.method;\n\n // Rebuild key if any key component changed\n const role = data.role ?? existing.role;\n const resource = data.resource ?? existing.resource;\n const scope = data.scope ?? existing.scope;\n data.permissionKey = `${role}#${resource}#${scope}`;\n\n // Check for duplicate key if components changed\n if (data.permissionKey !== existing.permissionKey) {\n const conflict = await this.repo.findByPermissionKey(data.permissionKey);\n if (conflict) {\n throw new ErrorHttp({ code: 409, error: \"Conflict\" }, `Permission \"${data.permissionKey}\" already exists`);\n }\n }\n\n const updated = await this.repo.update(data);\n\n this.cache.clear();\n return updated;\n }\n\n // ---------------------------------------------------------------------------\n // CRUD — delete\n // ---------------------------------------------------------------------------\n\n async deletePermission(id: string): Promise<boolean> {\n if (!id) throw new ErrorHttp({ code: 400, error: \"BadRequest\" }, \"Permission id is required\");\n\n const existing = await this.repo.findById(id);\n if (!existing) throw new ErrorHttp({ code: 404, error: \"NotFound\" }, `Permission \"${id}\" not found`);\n\n const result = await this.repo.delete(id);\n\n this.cache.clear();\n return result;\n }\n\n // ---------------------------------------------------------------------------\n // CRUD — list\n // ---------------------------------------------------------------------------\n\n async listPermissions(filter?: Filter): Promise<List<Partial<Permission>>> {\n return this.repo.findByIndex(filter);\n }\n\n // ---------------------------------------------------------------------------\n // Cache control (for testing)\n // ---------------------------------------------------------------------------\n\n clearCache(): void {\n this.cache.clear();\n }\n}\n"]}
@@ -80,7 +80,7 @@ const parseHttpRequest = (event, config) => {
80
80
  headers: { ...event?.headers },
81
81
  policy: findMatchedPolicy(event.httpMethod, eventResourcePath, config.ENDPOINT_POLICY),
82
82
  };
83
- if (!isAdmin && parsedParams.policy.access.includes(index_1.Access.OWNER)) {
83
+ if (!isAdmin && parsedParams.policy.access && parsedParams.policy.access.includes(index_1.Access.OWNER)) {
84
84
  if (isParent)
85
85
  parsedParams.filter[config.OWNER_PARENT_ID_FIELD_NAME ?? "ownerParentId"] = profileId;
86
86
  else
@@ -1 +1 @@
1
- {"version":3,"file":"http.util.js","sourceRoot":"","sources":["../../../src/utils/http/http.util.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Access,\n CognitoUser,\n EndpointPolicy,\n EntityConfig,\n Filter,\n HttpMethod,\n RequestType,\n ResponseFields,\n SortOrder,\n toCaseInsensitive,\n} from \"../../index\";\nimport { APIGatewayProxyEvent } from \"aws-lambda\";\nimport { getFirst, normalizeLower, toArray, trimSpecialChar } from \"../string.util\";\n\nexport type APIResponse = {\n statusCode: number;\n headers?: Record<string, string>;\n body: string;\n};\n\nexport type APIResponseOptions = {\n origin?: string;\n contentType: string;\n fields?: ResponseFields;\n};\n\nexport const DEFAULT_API_RESPONSE_OPTIONS: APIResponseOptions = {\n origin: \"*\",\n contentType: \"application/json\",\n};\n\nexport const createApiResponse = (statusCode: number, body: any, options?: APIResponseOptions): APIResponse => {\n const { origin, contentType } = options || DEFAULT_API_RESPONSE_OPTIONS;\n\n return {\n statusCode: statusCode,\n body: JSON.stringify(body),\n headers: {\n \"Access-Control-Allow-Origin\": origin || DEFAULT_API_RESPONSE_OPTIONS.origin,\n \"Content-Type\": contentType || DEFAULT_API_RESPONSE_OPTIONS.contentType,\n },\n };\n};\n\nexport interface HttpRequest<B = any, Q = any, P = any> {\n event: any;\n methode: HttpMethod;\n resourcePath: string;\n body?: B;\n queryStringParameters?: Q;\n filter?: Filter;\n customQueryParameters?: Record<string, string>;\n multiValueQueryStringParameters?: Q;\n pathParameters?: P;\n identity?: CognitoUser;\n headers?: Record<string, string>;\n requestType: RequestType;\n policy: EndpointPolicy;\n entityId: string;\n profileId?: string;\n parentId?: string;\n}\n\nexport const parseHttpRequest = (event: APIGatewayProxyEvent, config: EntityConfig): HttpRequest => {\n const identity = event?.requestContext?.authorizer?.claims;\n\n // request user data\n const groupsCognito = toArray(identity?.[\"cognito:groups\"]);\n\n const username = identity?.[\"cognito:username\"] || \"\";\n const userId = identity?.sub || \"\";\n const profileId = identity?.profile || username;\n const parentId: string | undefined = identity?.[\"custom:parentId\"];\n\n const adminGroups = new Set(normalizeLower(toArray(config.ADMIN_GROUP_NAME)));\n const groups = normalizeLower(toArray(groupsCognito));\n const isAdmin = groups.some((g) => adminGroups.has(g));\n let requestType: RequestType = RequestType.GUEST;\n let isParent: boolean = false;\n\n if (identity?.[\"custom:isParent\"] != null) {\n isParent = identity[\"custom:isParent\"] === \"1\";\n }\n\n if (isAdmin) {\n requestType = RequestType.ADMIN;\n } else if (profileId || userId) requestType = RequestType.USER;\n\n const entityId = decodeURIComponent(event?.pathParameters?.id || \"\");\n const eventResourcePath = event?.requestContext?.resourcePath;\n const resourcePath = event.httpMethod + \" \" + eventResourcePath;\n\n const parsedParams: HttpRequest = {\n event: event,\n methode: event.httpMethod as HttpMethod,\n queryStringParameters: event?.queryStringParameters || undefined,\n\n filter: event?.queryStringParameters\n ? parseFilter(\n event?.queryStringParameters as Record<string, any>,\n event.multiValueQueryStringParameters[\"searchBy\"],\n )\n : {},\n\n multiValueQueryStringParameters: event?.multiValueQueryStringParameters || undefined,\n pathParameters: event?.pathParameters || undefined,\n body: undefined,\n identity: identity\n ? {\n ...identity,\n isParent,\n isAdmin,\n parentId,\n groups,\n username,\n Authorization: event?.headers?.Authorization,\n identityId:\n event && \"x-cognito-identity-id\" in event.headers ? event.headers[\"x-cognito-identity-id\"] : undefined,\n }\n : undefined,\n // username,\n // userId,\n // isAdmin,\n profileId,\n parentId,\n requestType,\n resourcePath,\n entityId: entityId === \"null\" || entityId === \"undefined\" ? profileId : entityId,\n // groups,\n headers: { ...event?.headers },\n policy: findMatchedPolicy(event.httpMethod as HttpMethod, eventResourcePath, config.ENDPOINT_POLICY),\n };\n\n if (!isAdmin && parsedParams.policy.access.includes(Access.OWNER)) {\n if (isParent) parsedParams.filter[config.OWNER_PARENT_ID_FIELD_NAME ?? \"ownerParentId\"] = profileId;\n else parsedParams.filter[config.OWNER_ID_FIELD_NAME ?? \"profileId\"] = profileId;\n if (parentId) parsedParams.filter[config.OWNER_PARENT_ID_FIELD_NAME ?? \"ownerParentId\"] = parentId;\n }\n\n if (event?.body) parsedParams.body = typeof event.body === \"string\" ? JSON.parse(event.body) : event.body;\n\n return parsedParams;\n};\n\nexport function parseFilter(params: Record<string, any> | string, searchBy?: string[]): Filter {\n const result: Filter = {};\n\n if (searchBy && searchBy.length > 0) {\n result.searchBy = searchBy;\n }\n\n // If the params is a string (URL query string), parse it first\n let parsedParams: Record<string, any>;\n if (typeof params === \"string\") {\n parsedParams = toRecord(params);\n } else {\n parsedParams = params;\n }\n\n parsedParams.searchKeyword = getFirst(parsedParams.searchKeyword);\n\n const parseParam = (key: string, parseFunc: (value: string) => any) => {\n const value = parsedParams[key];\n if (value !== undefined && value !== null && String(value).trim() !== \"\") {\n result[key] = parseFunc(value);\n }\n };\n\n parseParam(\"page\", (value) => Number.parseInt(value, 10));\n parseParam(\"size\", (value) => Number.parseInt(value, 10));\n parseParam(\"sortBy\", (value) => value);\n parseParam(\"sort\", (value) => value as SortOrder);\n // parseParam(\"searchBy\", (value) => searchBy);\n parseParam(\"searchKeyword\", (value) => toCaseInsensitive(value));\n parseParam(\"lastKey\", (value) => value);\n parseParam(\"indexName\", (value) => value);\n parseParam(\"indexValue\", (value) => value);\n\n const parseRangeValue = (value: any) => {\n // If value is already a number, return it\n if (typeof value === \"number\") {\n return value;\n }\n\n // If the value is already a Date, return it\n if (value instanceof Date) {\n return value;\n }\n\n // Convert to string for parsing\n const stringValue = String(value);\n\n // Check if it's a valid date first (before number parsing)\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(stringValue) || /^\\d{4}\\.\\d{2}\\.\\d{2}/.test(stringValue)) {\n const date = new Date(stringValue);\n if (!Number.isNaN(date.getTime())) return date;\n }\n\n // Check for another date format that might be used in range filters\n if (/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/.test(stringValue)) {\n const date = new Date(stringValue);\n if (!Number.isNaN(date.getTime())) return date;\n }\n\n // Check if it's a valid number (including decimals)\n const numberValue = Number.parseFloat(stringValue);\n if (!Number.isNaN(numberValue)) {\n // Handle zero values (both \"0\" and \"0.0\" should become 0)\n if (numberValue === 0) {\n return 0;\n }\n // Handle integer values\n if (Number.isInteger(numberValue)) {\n return Number.parseInt(stringValue, 10);\n }\n return numberValue;\n }\n\n return value;\n };\n\n // Initialize rangeFilters array\n result.rangeFilters = [];\n\n // Auto-detect range filter patterns with min_ and max_ prefixes\n for (const key in parsedParams) {\n const value = parsedParams[key];\n if (value !== undefined && value !== null && String(value).trim() !== \"\") {\n // Check for min_ and max_ patterns\n const minMatch = key.match(/^min_(.+)$/i);\n const maxMatch = key.match(/^max_(.+)$/i);\n\n if (minMatch) {\n const fieldName = minMatch[1]; // Remove .toLowerCase() to preserve case\n // Find existing range filter or create new one\n let rangeFilter = result.rangeFilters!.find((rf) => rf.fieldName === fieldName);\n if (!rangeFilter) {\n rangeFilter = { fieldName };\n result.rangeFilters!.push(rangeFilter);\n }\n rangeFilter.minValue = parseRangeValue(value);\n } else if (maxMatch) {\n const fieldName = maxMatch[1]; // Remove .toLowerCase() to preserve case\n // Find existing range filter or create new one\n let rangeFilter = result.rangeFilters!.find((rf) => rf.fieldName === fieldName);\n if (!rangeFilter) {\n rangeFilter = { fieldName };\n result.rangeFilters!.push(rangeFilter);\n }\n rangeFilter.maxValue = parseRangeValue(value);\n } else if (!(key in result)) {\n result[key] = value;\n }\n }\n }\n\n // Clean up empty rangeFilters array\n if (result.rangeFilters!.length === 0) {\n delete result.rangeFilters;\n }\n\n return result;\n}\n\nfunction smartParse(value: string): any {\n if (value.includes(\"*\")) return value;\n\n // Boolean\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n\n // Integer\n if (/^-?\\d+$/.test(value)) return parseInt(value, 10);\n\n // Float / Double\n if (/^-?\\d*\\.\\d+$/.test(value)) return parseFloat(value);\n\n // ISO Date (YYYY-MM-DD) or Dot Date (YYYY.MM.DD)\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n const date = new Date(value);\n if (!isNaN(date.getTime())) return date;\n }\n if (/^\\d{4}\\.\\d{2}\\.\\d{2}/.test(value)) {\n // Convert to ISO format for Date constructor\n const isoValue = value.replace(/\\./g, \"-\");\n const date = new Date(isoValue);\n if (!isNaN(date.getTime())) return date;\n }\n\n if (typeof value === \"string\" && value.includes(\",\")) {\n const valueList = value.split(\",\");\n for (let i = 1; i < valueList.length; i++) {\n valueList[i] = smartParse(valueList[i]);\n }\n return valueList;\n }\n\n // Default: string\n return value;\n}\n\nexport function toRecord(queryString: string): Record<string, any> {\n const result: Record<string, any> = {};\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const [key, value] = pair.split(\"=\");\n if (key && value !== undefined) {\n result[key] = smartParse(decodeURIComponent(value));\n }\n }\n\n return result;\n}\n\nexport function findMatchedPolicy(methode: HttpMethod, path: string, policies: EndpointPolicy[]): EndpointPolicy {\n if (!methode || !path || !policies.length) {\n return null;\n }\n\n return policies.find((policy) => policy.method === methode && trimSpecialChar(policy.path) === trimSpecialChar(path));\n}\n"]}
1
+ {"version":3,"file":"http.util.js","sourceRoot":"","sources":["../../../src/utils/http/http.util.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Access,\n CognitoUser,\n EndpointPolicy,\n EntityConfig,\n Filter,\n HttpMethod,\n RequestType,\n ResponseFields,\n SortOrder,\n toCaseInsensitive,\n} from \"../../index\";\nimport { APIGatewayProxyEvent } from \"aws-lambda\";\nimport { getFirst, normalizeLower, toArray, trimSpecialChar } from \"../string.util\";\n\nexport type APIResponse = {\n statusCode: number;\n headers?: Record<string, string>;\n body: string;\n};\n\nexport type APIResponseOptions = {\n origin?: string;\n contentType: string;\n fields?: ResponseFields;\n};\n\nexport const DEFAULT_API_RESPONSE_OPTIONS: APIResponseOptions = {\n origin: \"*\",\n contentType: \"application/json\",\n};\n\nexport const createApiResponse = (statusCode: number, body: any, options?: APIResponseOptions): APIResponse => {\n const { origin, contentType } = options || DEFAULT_API_RESPONSE_OPTIONS;\n\n return {\n statusCode: statusCode,\n body: JSON.stringify(body),\n headers: {\n \"Access-Control-Allow-Origin\": origin || DEFAULT_API_RESPONSE_OPTIONS.origin,\n \"Content-Type\": contentType || DEFAULT_API_RESPONSE_OPTIONS.contentType,\n },\n };\n};\n\nexport interface HttpRequest<B = any, Q = any, P = any> {\n event: any;\n methode: HttpMethod;\n resourcePath: string;\n body?: B;\n queryStringParameters?: Q;\n filter?: Filter;\n customQueryParameters?: Record<string, string>;\n multiValueQueryStringParameters?: Q;\n pathParameters?: P;\n identity?: CognitoUser;\n headers?: Record<string, string>;\n requestType: RequestType;\n policy: EndpointPolicy;\n entityId: string;\n profileId?: string;\n parentId?: string;\n}\n\nexport const parseHttpRequest = (event: APIGatewayProxyEvent, config: EntityConfig): HttpRequest => {\n const identity = event?.requestContext?.authorizer?.claims;\n\n // request user data\n const groupsCognito = toArray(identity?.[\"cognito:groups\"]);\n\n const username = identity?.[\"cognito:username\"] || \"\";\n const userId = identity?.sub || \"\";\n const profileId = identity?.profile || username;\n const parentId: string | undefined = identity?.[\"custom:parentId\"];\n\n const adminGroups = new Set(normalizeLower(toArray(config.ADMIN_GROUP_NAME)));\n const groups = normalizeLower(toArray(groupsCognito));\n const isAdmin = groups.some((g) => adminGroups.has(g));\n let requestType: RequestType = RequestType.GUEST;\n let isParent: boolean = false;\n\n if (identity?.[\"custom:isParent\"] != null) {\n isParent = identity[\"custom:isParent\"] === \"1\";\n }\n\n if (isAdmin) {\n requestType = RequestType.ADMIN;\n } else if (profileId || userId) requestType = RequestType.USER;\n\n const entityId = decodeURIComponent(event?.pathParameters?.id || \"\");\n const eventResourcePath = event?.requestContext?.resourcePath;\n const resourcePath = event.httpMethod + \" \" + eventResourcePath;\n\n const parsedParams: HttpRequest = {\n event: event,\n methode: event.httpMethod as HttpMethod,\n queryStringParameters: event?.queryStringParameters || undefined,\n\n filter: event?.queryStringParameters\n ? parseFilter(\n event?.queryStringParameters as Record<string, any>,\n event.multiValueQueryStringParameters[\"searchBy\"],\n )\n : {},\n\n multiValueQueryStringParameters: event?.multiValueQueryStringParameters || undefined,\n pathParameters: event?.pathParameters || undefined,\n body: undefined,\n identity: identity\n ? {\n ...identity,\n isParent,\n isAdmin,\n parentId,\n groups,\n username,\n Authorization: event?.headers?.Authorization,\n identityId:\n event && \"x-cognito-identity-id\" in event.headers ? event.headers[\"x-cognito-identity-id\"] : undefined,\n }\n : undefined,\n // username,\n // userId,\n // isAdmin,\n profileId,\n parentId,\n requestType,\n resourcePath,\n entityId: entityId === \"null\" || entityId === \"undefined\" ? profileId : entityId,\n // groups,\n headers: { ...event?.headers },\n policy: findMatchedPolicy(event.httpMethod as HttpMethod, eventResourcePath, config.ENDPOINT_POLICY),\n };\n\n if (!isAdmin && parsedParams.policy.access && parsedParams.policy.access.includes(Access.OWNER)) {\n if (isParent) parsedParams.filter[config.OWNER_PARENT_ID_FIELD_NAME ?? \"ownerParentId\"] = profileId;\n else parsedParams.filter[config.OWNER_ID_FIELD_NAME ?? \"profileId\"] = profileId;\n if (parentId) parsedParams.filter[config.OWNER_PARENT_ID_FIELD_NAME ?? \"ownerParentId\"] = parentId;\n }\n\n if (event?.body) parsedParams.body = typeof event.body === \"string\" ? JSON.parse(event.body) : event.body;\n\n return parsedParams;\n};\n\nexport function parseFilter(params: Record<string, any> | string, searchBy?: string[]): Filter {\n const result: Filter = {};\n\n if (searchBy && searchBy.length > 0) {\n result.searchBy = searchBy;\n }\n\n // If the params is a string (URL query string), parse it first\n let parsedParams: Record<string, any>;\n if (typeof params === \"string\") {\n parsedParams = toRecord(params);\n } else {\n parsedParams = params;\n }\n\n parsedParams.searchKeyword = getFirst(parsedParams.searchKeyword);\n\n const parseParam = (key: string, parseFunc: (value: string) => any) => {\n const value = parsedParams[key];\n if (value !== undefined && value !== null && String(value).trim() !== \"\") {\n result[key] = parseFunc(value);\n }\n };\n\n parseParam(\"page\", (value) => Number.parseInt(value, 10));\n parseParam(\"size\", (value) => Number.parseInt(value, 10));\n parseParam(\"sortBy\", (value) => value);\n parseParam(\"sort\", (value) => value as SortOrder);\n // parseParam(\"searchBy\", (value) => searchBy);\n parseParam(\"searchKeyword\", (value) => toCaseInsensitive(value));\n parseParam(\"lastKey\", (value) => value);\n parseParam(\"indexName\", (value) => value);\n parseParam(\"indexValue\", (value) => value);\n\n const parseRangeValue = (value: any) => {\n // If value is already a number, return it\n if (typeof value === \"number\") {\n return value;\n }\n\n // If the value is already a Date, return it\n if (value instanceof Date) {\n return value;\n }\n\n // Convert to string for parsing\n const stringValue = String(value);\n\n // Check if it's a valid date first (before number parsing)\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(stringValue) || /^\\d{4}\\.\\d{2}\\.\\d{2}/.test(stringValue)) {\n const date = new Date(stringValue);\n if (!Number.isNaN(date.getTime())) return date;\n }\n\n // Check for another date format that might be used in range filters\n if (/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/.test(stringValue)) {\n const date = new Date(stringValue);\n if (!Number.isNaN(date.getTime())) return date;\n }\n\n // Check if it's a valid number (including decimals)\n const numberValue = Number.parseFloat(stringValue);\n if (!Number.isNaN(numberValue)) {\n // Handle zero values (both \"0\" and \"0.0\" should become 0)\n if (numberValue === 0) {\n return 0;\n }\n // Handle integer values\n if (Number.isInteger(numberValue)) {\n return Number.parseInt(stringValue, 10);\n }\n return numberValue;\n }\n\n return value;\n };\n\n // Initialize rangeFilters array\n result.rangeFilters = [];\n\n // Auto-detect range filter patterns with min_ and max_ prefixes\n for (const key in parsedParams) {\n const value = parsedParams[key];\n if (value !== undefined && value !== null && String(value).trim() !== \"\") {\n // Check for min_ and max_ patterns\n const minMatch = key.match(/^min_(.+)$/i);\n const maxMatch = key.match(/^max_(.+)$/i);\n\n if (minMatch) {\n const fieldName = minMatch[1]; // Remove .toLowerCase() to preserve case\n // Find existing range filter or create new one\n let rangeFilter = result.rangeFilters!.find((rf) => rf.fieldName === fieldName);\n if (!rangeFilter) {\n rangeFilter = { fieldName };\n result.rangeFilters!.push(rangeFilter);\n }\n rangeFilter.minValue = parseRangeValue(value);\n } else if (maxMatch) {\n const fieldName = maxMatch[1]; // Remove .toLowerCase() to preserve case\n // Find existing range filter or create new one\n let rangeFilter = result.rangeFilters!.find((rf) => rf.fieldName === fieldName);\n if (!rangeFilter) {\n rangeFilter = { fieldName };\n result.rangeFilters!.push(rangeFilter);\n }\n rangeFilter.maxValue = parseRangeValue(value);\n } else if (!(key in result)) {\n result[key] = value;\n }\n }\n }\n\n // Clean up empty rangeFilters array\n if (result.rangeFilters!.length === 0) {\n delete result.rangeFilters;\n }\n\n return result;\n}\n\nfunction smartParse(value: string): any {\n if (value.includes(\"*\")) return value;\n\n // Boolean\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n\n // Integer\n if (/^-?\\d+$/.test(value)) return parseInt(value, 10);\n\n // Float / Double\n if (/^-?\\d*\\.\\d+$/.test(value)) return parseFloat(value);\n\n // ISO Date (YYYY-MM-DD) or Dot Date (YYYY.MM.DD)\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n const date = new Date(value);\n if (!isNaN(date.getTime())) return date;\n }\n if (/^\\d{4}\\.\\d{2}\\.\\d{2}/.test(value)) {\n // Convert to ISO format for Date constructor\n const isoValue = value.replace(/\\./g, \"-\");\n const date = new Date(isoValue);\n if (!isNaN(date.getTime())) return date;\n }\n\n if (typeof value === \"string\" && value.includes(\",\")) {\n const valueList = value.split(\",\");\n for (let i = 1; i < valueList.length; i++) {\n valueList[i] = smartParse(valueList[i]);\n }\n return valueList;\n }\n\n // Default: string\n return value;\n}\n\nexport function toRecord(queryString: string): Record<string, any> {\n const result: Record<string, any> = {};\n const pairs = queryString.split(\"&\");\n\n for (const pair of pairs) {\n const [key, value] = pair.split(\"=\");\n if (key && value !== undefined) {\n result[key] = smartParse(decodeURIComponent(value));\n }\n }\n\n return result;\n}\n\nexport function findMatchedPolicy(methode: HttpMethod, path: string, policies: EndpointPolicy[]): EndpointPolicy {\n if (!methode || !path || !policies.length) {\n return null;\n }\n\n return policies.find((policy) => policy.method === methode && trimSpecialChar(policy.path) === trimSpecialChar(path));\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aws-service-stack",
3
- "version": "0.18.392",
3
+ "version": "0.18.394",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "author": "chinggis.systems",