@universis/janitor 2.4.4 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1931,12 +1931,139 @@ class DisableNetworkRestrictAccess extends NetworkRestrictAccess {
1931
1931
  }
1932
1932
  }
1933
1933
 
1934
+ class EnableReadAccessScope extends common.ApplicationService {
1935
+ /**
1936
+ *
1937
+ * @param {import('@themost/express').ExpressDataApplication|import('@themost/common').ApplicationBase} app
1938
+ */
1939
+ constructor(app) {
1940
+ super(app);
1941
+ /**
1942
+ * @type {import('rxjs').Observable<import('express').Application>}
1943
+ */
1944
+ const container = app && app.container;
1945
+ if (container) {
1946
+ container.subscribe((container) => {
1947
+ if (container) {
1948
+ for (const scope of this.clientScopes) {
1949
+ this.enable(scope);
1950
+ }
1951
+ }
1952
+ });
1953
+ }
1954
+ }
1955
+
1956
+ get clientScopes() {
1957
+ return [
1958
+ 'students',
1959
+ 'teachers',
1960
+ 'registrar'];
1961
+
1962
+ }
1963
+
1964
+ /**
1965
+ * @protected
1966
+ * @param {string} scope
1967
+ */
1968
+ enable(scope) {
1969
+ const searchScope = scope;
1970
+ const targetScope = scope + ':read';
1971
+ // get schema loader strategy for enumerating models
1972
+ const schemaLoader = this.getApplication().getConfiguration().getStrategy(data.SchemaLoaderStrategy);
1973
+ if (schemaLoader) {
1974
+ const models = schemaLoader.getModels();
1975
+ let updated = 0;
1976
+ // enumerate models that includes scope based privileges
1977
+ // where mask is 1 (read)
1978
+ for (const model of models) {
1979
+ /**
1980
+ * @type {import('@themost/common').DataModelProperties}
1981
+ */
1982
+ const definition = schemaLoader.getModelDefinition(model);
1983
+ if (Array.isArray(definition.privileges)) {
1984
+ const privileges = definition.privileges.filter((item) => {
1985
+ return item.mask === 1 && Array.isArray(item.scope) && item.scope.includes(searchScope);
1986
+ });
1987
+ let shouldUpdate = false;
1988
+ if (privileges.length > 0) {
1989
+ shouldUpdate = true;
1990
+ // add target scope to privileges
1991
+ for (const privilege of privileges) {
1992
+ if (!privilege.scope.includes(targetScope)) {
1993
+ privilege.scope.push(targetScope);
1994
+ }
1995
+ }
1996
+ }
1997
+ // get fields that includes scope based privileges
1998
+ const fields = definition.fields.filter((item) => {
1999
+ return Array.isArray(item.privileges);
2000
+ }).filter((item) => {
2001
+ const privileges = item.privileges.filter((privilege) => {
2002
+ return privilege.mask === 1 && Array.isArray(privilege.scope) && privilege.scope.includes(searchScope);
2003
+ });
2004
+ return privileges.length > 0;
2005
+ });
2006
+ if (fields.length > 0) {
2007
+ shouldUpdate = true;
2008
+ for (const field of fields) {
2009
+ const privileges = field.privileges.filter((privilege) => {
2010
+ return privilege.mask === 1 && Array.isArray(privilege.scope) && privilege.scope.includes(searchScope);
2011
+ });
2012
+ for (const privilege of privileges) {
2013
+ if (!privilege.scope.includes(targetScope)) {
2014
+ privilege.scope.push(targetScope);
2015
+ }
2016
+ }
2017
+ }
2018
+ }
2019
+ if (shouldUpdate) {
2020
+ updated++;
2021
+ // update model definition
2022
+ schemaLoader.setModelDefinition(definition);
2023
+ }
2024
+ }
2025
+ }
2026
+ if (updated > 0) {
2027
+ common.TraceUtils.log(`${this.constructor.name}: Updated ${updated} model definition(s) to include scope "${targetScope}"`);
2028
+ }
2029
+ }
2030
+
2031
+ const scopeConfiguration = this.getApplication().getConfiguration().getStrategy(ScopeAccessConfiguration);
2032
+ if (scopeConfiguration) {
2033
+ const elements = scopeConfiguration.elements.
2034
+ filter((item) => item.scope.includes(searchScope)).
2035
+ filter((item) => item.access.includes('read'));
2036
+ if (elements.length > 0) {
2037
+ const insertElements = [];
2038
+ for (const element of elements) {
2039
+ insertElements.push({
2040
+ insertAfter: element,
2041
+ resource: element.resource,
2042
+ scope: [targetScope],
2043
+ access: ['read']
2044
+ });
2045
+ }
2046
+ for (const { insertAfter, resource, scope, access } of insertElements) {
2047
+ const index = scopeConfiguration.elements.findIndex((element) => element === insertAfter);
2048
+ scopeConfiguration.elements.splice(index + 1, 0, {
2049
+ resource,
2050
+ scope,
2051
+ access
2052
+ });
2053
+ }
2054
+ common.TraceUtils.log(`${this.constructor.name}: Updated ${elements.length} scope access configuration(s) to include scope "${targetScope}"`);
2055
+ }
2056
+ }
2057
+ }
2058
+ }
2059
+
1934
2060
  exports.AppRateLimitService = AppRateLimitService;
1935
2061
  exports.AppSpeedLimitService = AppSpeedLimitService;
1936
2062
  exports.DefaultScopeAccessConfiguration = DefaultScopeAccessConfiguration;
1937
2063
  exports.DisableNetworkRestrictAccess = DisableNetworkRestrictAccess;
1938
2064
  exports.DisableUserClientScopeVerification = DisableUserClientScopeVerification;
1939
2065
  exports.EnableNetworkRestrictAccess = EnableNetworkRestrictAccess;
2066
+ exports.EnableReadAccessScope = EnableReadAccessScope;
1940
2067
  exports.EnableScopeAccessConfiguration = EnableScopeAccessConfiguration;
1941
2068
  exports.ExtendScopeAccessConfiguration = ExtendScopeAccessConfiguration;
1942
2069
  exports.HttpAccountDisabled = HttpAccountDisabled;