proto.io 0.0.228 → 0.0.229

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.
Files changed (65) hide show
  1. package/README.md +1017 -0
  2. package/dist/adapters/file/aliyun-oss.d.mts +26 -0
  3. package/dist/adapters/file/aliyun-oss.d.mts.map +1 -0
  4. package/dist/adapters/file/aliyun-oss.d.ts +3 -3
  5. package/dist/adapters/file/database.d.mts +23 -0
  6. package/dist/adapters/file/database.d.mts.map +1 -0
  7. package/dist/adapters/file/database.d.ts +2 -2
  8. package/dist/adapters/file/database.js +1 -1
  9. package/dist/adapters/file/database.mjs +1 -1
  10. package/dist/adapters/file/filesystem.d.mts +25 -0
  11. package/dist/adapters/file/filesystem.d.mts.map +1 -0
  12. package/dist/adapters/file/filesystem.d.ts +3 -3
  13. package/dist/adapters/file/google-cloud-storage.d.mts +29 -0
  14. package/dist/adapters/file/google-cloud-storage.d.mts.map +1 -0
  15. package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
  16. package/dist/adapters/storage/postgres.d.mts +299 -0
  17. package/dist/adapters/storage/postgres.d.mts.map +1 -0
  18. package/dist/adapters/storage/postgres.d.ts +5 -1
  19. package/dist/adapters/storage/postgres.d.ts.map +1 -1
  20. package/dist/adapters/storage/postgres.js +182 -74
  21. package/dist/adapters/storage/postgres.js.map +1 -1
  22. package/dist/adapters/storage/postgres.mjs +182 -74
  23. package/dist/adapters/storage/postgres.mjs.map +1 -1
  24. package/dist/client.d.mts +16 -0
  25. package/dist/client.d.mts.map +1 -0
  26. package/dist/client.d.ts +3 -3
  27. package/dist/client.js +1 -1
  28. package/dist/client.mjs +2 -2
  29. package/dist/index.d.mts +151 -0
  30. package/dist/index.d.mts.map +1 -0
  31. package/dist/index.d.ts +3 -3
  32. package/dist/index.js +50 -7
  33. package/dist/index.js.map +1 -1
  34. package/dist/index.mjs +51 -8
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/internals/{base-CW4QHAo3.d.ts → base-Bhrj5Pq1.d.ts} +2 -2
  37. package/dist/internals/{base-CW4QHAo3.d.ts.map → base-Bhrj5Pq1.d.ts.map} +1 -1
  38. package/dist/internals/base-CiZHXD0o.d.mts +27 -0
  39. package/dist/internals/base-CiZHXD0o.d.mts.map +1 -0
  40. package/dist/internals/chunk-Cp2QN7ug.d.mts +17 -0
  41. package/dist/internals/chunk-Cp2QN7ug.d.mts.map +1 -0
  42. package/dist/internals/{chunk-DPgxK2_o.d.ts → chunk-o7lWIP-f.d.ts} +3 -3
  43. package/dist/internals/{chunk-DPgxK2_o.d.ts.map → chunk-o7lWIP-f.d.ts.map} +1 -1
  44. package/dist/internals/{index-vOFh8pVc.js → index-B0TO6h9r.js} +8 -1
  45. package/dist/internals/index-B0TO6h9r.js.map +1 -0
  46. package/dist/internals/{index-CywcwPk-.d.ts → index-B710pfTH.d.ts} +2 -2
  47. package/dist/internals/{index-CywcwPk-.d.ts.map → index-B710pfTH.d.ts.map} +1 -1
  48. package/dist/internals/{index-BWZIV3_T.mjs → index-DG2-4tQ1.mjs} +8 -1
  49. package/dist/internals/index-DG2-4tQ1.mjs.map +1 -0
  50. package/dist/internals/index-DwjvuRyl.d.mts +92 -0
  51. package/dist/internals/index-DwjvuRyl.d.mts.map +1 -0
  52. package/dist/internals/index-OwgXw07h.d.mts +2107 -0
  53. package/dist/internals/index-OwgXw07h.d.mts.map +1 -0
  54. package/dist/internals/{index-h4KGKuhq.d.ts → index-OwgXw07h.d.ts} +45 -3
  55. package/dist/internals/index-OwgXw07h.d.ts.map +1 -0
  56. package/dist/internals/{validator-Bc1jRJfA.js → validator-CFlx3oyq.js} +33 -1
  57. package/dist/internals/validator-CFlx3oyq.js.map +1 -0
  58. package/dist/internals/{validator-Boj1PUjM.mjs → validator-DubDY921.mjs} +32 -2
  59. package/dist/internals/validator-DubDY921.mjs.map +1 -0
  60. package/package.json +7 -19
  61. package/dist/internals/index-BWZIV3_T.mjs.map +0 -1
  62. package/dist/internals/index-h4KGKuhq.d.ts.map +0 -1
  63. package/dist/internals/index-vOFh8pVc.js.map +0 -1
  64. package/dist/internals/validator-Bc1jRJfA.js.map +0 -1
  65. package/dist/internals/validator-Boj1PUjM.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import _ from 'lodash';
2
2
  import { Server } from '@o2ter/server-js';
3
- import { Q as QueryValidator, a as QueryExpression, r as resolveColumn, b as resolveDataType, c as QuerySelector } from './internals/validator-Boj1PUjM.mjs';
3
+ import { Q as QueryValidator, a as QueryExpression, b as QueryAccumulator, r as resolveColumn, c as resolveDataType, d as QuerySelector } from './internals/validator-DubDY921.mjs';
4
4
  import { P as PVK } from './internals/private-CNw40LZ7.mjs';
5
5
  import { prototypes, asyncStream, isBinaryData, base64ToBuffer } from '@o2ter/utils-js';
6
- import { L as LiveQuerySubscription, T as TQuery, d as deserialize, s as serialize, a as TUser, P as ProtoType, _ as _logLevels } from './internals/index-BWZIV3_T.mjs';
7
- export { b as ProtoClient, c as classExtends } from './internals/index-BWZIV3_T.mjs';
6
+ import { L as LiveQuerySubscription, T as TQuery, d as deserialize, s as serialize, a as TUser, P as ProtoType, _ as _logLevels } from './internals/index-DG2-4tQ1.mjs';
7
+ export { b as ProtoClient, c as classExtends } from './internals/index-DG2-4tQ1.mjs';
8
8
  import { i as isPointer, a as isRelation, T as TObject, d as defaultObjectKeyTypes, b as isShape, c as isPrimitive } from './internals/index-CSOoWRr1.mjs';
9
9
  import jwt from 'jsonwebtoken';
10
10
  import { Blob } from 'node:buffer';
@@ -113,6 +113,16 @@ const dispatcher = (proto, options) => {
113
113
  throw Error('No permission');
114
114
  return proto.storage.find(decoded);
115
115
  },
116
+ async groupFind(query, accumulators) {
117
+ QueryValidator.recursiveCheck(query);
118
+ const _validator = await validator();
119
+ const decoded = _validator.decodeQuery(normalize(query), 'read');
120
+ const isGet = _validator.isGetMethod(decoded.filter);
121
+ if (!_validator.validateCLPs(query.className, isGet ? 'get' : 'find'))
122
+ throw Error('No permission');
123
+ const acc = _.mapValues(accumulators, x => QueryAccumulator.decode(x).simplify());
124
+ return proto.storage.groupFind(decoded, acc);
125
+ },
116
126
  async nonrefs(query) {
117
127
  QueryValidator.recursiveCheck(query);
118
128
  const _validator = await validator();
@@ -309,6 +319,9 @@ class _ProtoQuery extends TQuery {
309
319
  yield self._objectMethods(object);
310
320
  });
311
321
  }
322
+ groupFind(accumulators, options) {
323
+ return this._dispatcher(options).groupFind(this._queryOptions, accumulators);
324
+ }
312
325
  nonrefs(options) {
313
326
  const self = this;
314
327
  return asyncStream(async function* () {
@@ -523,6 +536,8 @@ const defaultSchema = {
523
536
  'User': {
524
537
  fields: {
525
538
  password: 'object',
539
+ password_history: 'array',
540
+ password_changed_at: 'date',
526
541
  },
527
542
  classLevelPermissions: {
528
543
  find: [],
@@ -532,7 +547,7 @@ const defaultSchema = {
532
547
  fieldLevelPermissions: {
533
548
  _expired_at: { create: [], update: [] },
534
549
  },
535
- secureFields: ['password'],
550
+ secureFields: ['password', 'password_history', 'password_changed_at'],
536
551
  },
537
552
  'Role': {
538
553
  fields: {
@@ -913,13 +928,39 @@ class ProtoInternal {
913
928
  throw Error('Invalid user object');
914
929
  if (_.isEmpty(password))
915
930
  throw Error('Invalid password');
931
+ const { maxPasswordHistory, validatorCallback, } = this.options.passwordPolicy || {};
932
+ if (validatorCallback) {
933
+ const isValid = await validatorCallback(password, user);
934
+ if (!isValid)
935
+ throw Error('Password does not meet the policy requirements');
936
+ }
916
937
  const { alg, ...opts } = this.options.passwordHashOptions;
917
938
  const hashed = await passwordHash(alg, password, opts);
939
+ let history = [];
940
+ if (maxPasswordHistory && maxPasswordHistory > 0) {
941
+ const _user = await proto.InsecureQuery('User')
942
+ .equalTo('_id', user.id)
943
+ .includes('_id', 'password_history')
944
+ .first(options);
945
+ history = _.slice(_user?.get('password_history') ?? [], 0, maxPasswordHistory);
946
+ for (const entry of history) {
947
+ const { alg, ...opts } = entry;
948
+ if (await verifyPassword(alg, password, opts)) {
949
+ throw Error('Cannot reuse previous passwords');
950
+ }
951
+ }
952
+ }
918
953
  await proto.InsecureQuery('User')
919
954
  .equalTo('_id', user.id)
920
955
  .includes('_id')
921
956
  .updateOne({
922
957
  password: { $set: hashed },
958
+ password_history: {
959
+ $set: maxPasswordHistory && maxPasswordHistory > 0
960
+ ? _.slice([{ ...hashed, password }, ...history], 0, maxPasswordHistory)
961
+ : [],
962
+ },
963
+ password_changed_at: { $set: new Date() },
923
964
  }, options);
924
965
  }
925
966
  async unsetPassword(proto, user, options) {
@@ -930,6 +971,7 @@ class ProtoInternal {
930
971
  .includes('_id')
931
972
  .updateOne({
932
973
  password: { $set: {} },
974
+ password_changed_at: { $set: new Date() },
933
975
  }, options);
934
976
  }
935
977
  async updateFile(proto, object, options) {
@@ -1974,7 +2016,7 @@ const verifyRelatedBy = (relatedBy) => {
1974
2016
  var classesRoute = (router, proto) => {
1975
2017
  const defaultHandler = async (req) => {
1976
2018
  const { name } = req.params;
1977
- const { operation, random, attributes, update, setOnInsert, relatedBy, silent, ...options } = deserialize(req.body);
2019
+ const { operation, accumulators, random, attributes, update, setOnInsert, relatedBy, silent, ...options } = deserialize(req.body);
1978
2020
  verifyRelatedBy(relatedBy);
1979
2021
  const payload = proto.connect(req);
1980
2022
  const query = relatedBy ? payload.Relation(payload.Object(relatedBy.className, relatedBy.id), relatedBy.key) : payload.Query(name);
@@ -1995,15 +2037,16 @@ var classesRoute = (router, proto) => {
1995
2037
  query[PVK].options.limit = query[PVK].options.limit ?? maxFetchLimit;
1996
2038
  if (query[PVK].options.limit > maxFetchLimit)
1997
2039
  throw Error('Query over limit');
1998
- return await query.find(opts);
2040
+ return query.find(opts);
1999
2041
  }
2042
+ case 'groupFind': return query.groupFind(accumulators, opts);
2000
2043
  case 'random':
2001
2044
  {
2002
2045
  const maxFetchLimit = payload[PVK].options.maxFetchLimit;
2003
2046
  query[PVK].options.limit = query[PVK].options.limit ?? maxFetchLimit;
2004
2047
  if (query[PVK].options.limit > maxFetchLimit)
2005
2048
  throw Error('Query over limit');
2006
- return await query.random(random, opts);
2049
+ return query.random(random, opts);
2007
2050
  }
2008
2051
  case 'nonrefs':
2009
2052
  {
@@ -2011,7 +2054,7 @@ var classesRoute = (router, proto) => {
2011
2054
  query[PVK].options.limit = query[PVK].options.limit ?? maxFetchLimit;
2012
2055
  if (query[PVK].options.limit > maxFetchLimit)
2013
2056
  throw Error('Query over limit');
2014
- return await query.nonrefs(opts);
2057
+ return query.nonrefs(opts);
2015
2058
  }
2016
2059
  case 'insert': return query.insert(attributes, opts);
2017
2060
  case 'insertMany': return query.insertMany(attributes, opts);