@telia-ace/alliance-portal 1.0.7-next.2 → 1.0.7-next.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @telia-ace/alliance-portal
2
2
 
3
+ ## 1.0.7-next.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 0c97bb2: Validate and define default values for environment config using Zod.
8
+ - 0c97bb2: Fully support portals with static Workspace and Customer.
9
+ - Updated dependencies [0c97bb2]
10
+ - Updated dependencies [0c97bb2]
11
+ - @telia-ace/alliance-internal-node-utilities@1.0.4-next.3
12
+
13
+ ## 1.0.7-next.3
14
+
15
+ ### Patch Changes
16
+
17
+ - 7ef3b70: Define `HEALTHCHECK` in Dockerfile.
18
+
3
19
  ## 1.0.7-next.2
4
20
 
5
21
  ### Patch Changes
@@ -1,4 +1,26 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"createAppController",{enumerable:true,get:function(){return createAppController}});const _axios=require("@nestjs/axios");const _common=require("@nestjs/common");const _config=require("@nestjs/config");const _terminus=require("@nestjs/terminus");const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");const _express=require("express");const _graphqlrequest=require("graphql-request");const _config1=require("./config");const _graphql=require("./graphql");function _ts_decorate(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect==="object"&&typeof Reflect.decorate==="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)if(d=decorators[i])r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r;return c>3&&r&&Object.defineProperty(target,key,r),r}function _ts_metadata(k,v){if(typeof Reflect==="object"&&typeof Reflect.metadata==="function")return Reflect.metadata(k,v)}function _ts_param(paramIndex,decorator){return function(target,key){decorator(target,key,paramIndex)}}function createAppController({}){let AppController=class AppController{signin(){}catchall(){return""}check(){return this.healthService.check([()=>this.redisHealthCheck.isHealthy()])}async cookiePolicy(){const policyUrl=this.configService.getOrThrow(_config1.ConfigKeys.WebprovisionsDistributionCookiePolicyUrl);const{data}=await this.httpService.axiosRef.get(policyUrl);return data}async index(req,workspaceSlug){let userHasAccess=false;try{const objectId=req.oidc.user.sub;const{user}=await (0,_graphqlrequest.request)(this.configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.DbEndpoint),_graphql.GetUserDocument,{objectId,workspaceSlug},{authorization:(0,_allianceinternalnodeutilities.createSystemUserToken)(this.configService)});userHasAccess=!!user.id}catch{}if(!userHasAccess){return htmlTemplate(unauthorizedPortalBody())}const distribution={opts:{},url:this.configService.getOrThrow(_config1.ConfigKeys.WebprovisionsDistributionUrl)};if(!req.query["wp-tag"]&&!req.query["wp-version"]){distribution.opts.tag=this.configService.getOrThrow(_config1.ConfigKeys.WebprovisionsTag)}this.logger.info("opening portal",{user:req.oidc.user,distribution,workspaceSlug});return htmlTemplate(portalBody({distribution,workspaceSlug}))}constructor(logger,configService,httpService,healthService,redisHealthCheck){this.logger=logger;this.configService=configService;this.httpService=httpService;this.healthService=healthService;this.redisHealthCheck=redisHealthCheck}};_ts_decorate([(0,_common.Get)("/signin-oidc"),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[])],AppController.prototype,"signin",null);_ts_decorate([(0,_common.Get)("/favicon*"),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[])],AppController.prototype,"catchall",null);_ts_decorate([(0,_common.Get)("/health"),(0,_terminus.HealthCheck)(),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[])],AppController.prototype,"check",null);_ts_decorate([(0,_common.Get)(["/:workspace/cookie-policy"]),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[])],AppController.prototype,"cookiePolicy",null);_ts_decorate([(0,_common.Get)(["/:workspace*"]),_ts_param(0,(0,_common.Req)()),_ts_param(1,(0,_common.Param)("workspace")),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[typeof _express.Request==="undefined"?Object:_express.Request,String])],AppController.prototype,"index",null);AppController=_ts_decorate([(0,_common.Controller)(),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[typeof _allianceinternalnodeutilities.LoggerService==="undefined"?Object:_allianceinternalnodeutilities.LoggerService,typeof _config.ConfigService==="undefined"?Object:_config.ConfigService,typeof _axios.HttpService==="undefined"?Object:_axios.HttpService,typeof _terminus.HealthCheckService==="undefined"?Object:_terminus.HealthCheckService,typeof _allianceinternalnodeutilities.RedisHealthIndicator==="undefined"?Object:_allianceinternalnodeutilities.RedisHealthIndicator])],AppController);return AppController}const loader=`
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});function _export(target,all){for(var name in all)Object.defineProperty(target,name,{enumerable:true,get:all[name]})}_export(exports,{GlobalFrameworkVariables:function(){return GlobalFrameworkVariables},createAppController:function(){return createAppController}});const _axios=require("@nestjs/axios");const _common=require("@nestjs/common");const _config=require("@nestjs/config");const _terminus=require("@nestjs/terminus");const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");const _express=require("express");const _graphqlrequest=require("graphql-request");const _config1=require("./config");const _graphql=require("./graphql");function _ts_decorate(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect==="object"&&typeof Reflect.decorate==="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)if(d=decorators[i])r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r;return c>3&&r&&Object.defineProperty(target,key,r),r}function _ts_metadata(k,v){if(typeof Reflect==="object"&&typeof Reflect.metadata==="function")return Reflect.metadata(k,v)}function _ts_param(paramIndex,decorator){return function(target,key){decorator(target,key,paramIndex)}}function createAppController(){const environmentWorkspace=process.env[_config1.ConfigKeys.Workspace];let AppController=class AppController{signin(){}favicon(){return""}health(){return this.healthService.check([()=>this.redisHealthCheck.isHealthy()])}async cookiePolicy(){const{data}=await this.httpService.axiosRef.get(this.wpPolicyUrl);return data}async index(req,workspaceParam){let userHasAccess=false;try{const objectId=req?.oidc?.user?.sub;const{user}=await (0,_graphqlrequest.request)(this.configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.DbEndpoint),_graphql.GetUserDocument,{objectId,workspaceSlug:environmentWorkspace||workspaceParam},{authorization:(0,_allianceinternalnodeutilities.createSystemUserToken)(this.configService)});userHasAccess=!!user.id}catch{}if(!userHasAccess){return htmlTemplate(unauthorizedPortalBody())}this.logger.info("opening portal",{user:req.oidc.user,workspaceSlug:environmentWorkspace||workspaceParam});return htmlTemplate(this.portalBody({excludeTag:!!req.query["wp-tag"]||!!req.query["wp-version"],workspaceSlug:environmentWorkspace||workspaceParam}))}portalBody({excludeTag,workspaceSlug}){const opts=excludeTag?{}:{tag:this.wpTag};const environmentCustomer=this.configService.get(_config1.ConfigKeys.Customer);let rootUrl=`window.origin + '/${workspaceSlug}'`;if(this.configService.get(_config1.ConfigKeys.OriginAsRootUrl)){rootUrl="window.origin"}else if(environmentCustomer){rootUrl=`window.origin + '/${environmentCustomer}/${workspaceSlug}'`}return`
2
+ <script>
3
+ window.${"__ALLIANCE_RUNTIME_ROOT_URL"} = ${rootUrl};
4
+ window.${"__ALLIANCE_WORKSPACE"} = '${workspaceSlug}';
5
+ window.${"__ALLIANCE_CUSTOMER"} = ${environmentCustomer?`'${environmentCustomer}'`:"undefined"};
6
+ </script>
7
+
8
+ <script>
9
+ /* WEBPROVISIONS */
10
+ !function(e,n){var o=n||{},c=document,t=window,s=function(n,o){e+=(e.indexOf("?")>-1?"&":"?")+encodeURIComponent(n)+"="
11
+ +encodeURIComponent(o)},i=/[?&]{1}(wp[^=]*)=([^&#]*)/g,r=c.getElementsByTagName("script")[0],p=c.createElement("script");p.type="module";e=e+"/index.js";
12
+ for(t.webprovisions=t.webprovisions||{_c:[],configure:function(){t.webprovisions._c.push(arguments)}};matches=i.exec(t.location.search);)
13
+ s(matches[1],matches[2]);Object.keys(o).forEach((function(e){s("wp-"+e,o[e])})),p.async=!0,p.src=e,r.parentNode.insertBefore(p,r)}
14
+ /**
15
+ * Configure the implementation by specifying a remote endpoint with optional arguments.
16
+ * url - The url to the remote endpoint for the implementation.
17
+ * args - Object containing optional arguments for the implementation.
18
+ */
19
+ ("${this.wpUrl}", ${JSON.stringify(opts)})
20
+ </script>
21
+
22
+ ${loader}
23
+ `}constructor(logger,configService,httpService,healthService,redisHealthCheck){this.logger=logger;this.configService=configService;this.httpService=httpService;this.healthService=healthService;this.redisHealthCheck=redisHealthCheck;this.wpUrl=this.configService.getOrThrow(_config1.ConfigKeys.WebprovisionsDistributionUrl);this.wpPolicyUrl=this.configService.get(_config1.ConfigKeys.WebprovisionsDistributionCookiePolicyUrl)||`${this.wpUrl}/cookie-policy.html`;this.wpTag=this.configService.get(_config1.ConfigKeys.WebprovisionsTag)}};_ts_decorate([(0,_common.Get)("/signin-oidc"),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[])],AppController.prototype,"signin",null);_ts_decorate([(0,_common.Get)("/favicon*"),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[])],AppController.prototype,"favicon",null);_ts_decorate([(0,_common.Get)("/health"),(0,_terminus.HealthCheck)(),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[])],AppController.prototype,"health",null);_ts_decorate([(0,_common.Get)(environmentWorkspace?"/cookie-policy":"/:workspace/cookie-policy"),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[])],AppController.prototype,"cookiePolicy",null);_ts_decorate([(0,_common.Get)(environmentWorkspace?"/*":"/:workspace*"),_ts_param(0,(0,_common.Req)()),_ts_param(1,(0,_common.Param)("workspace")),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[typeof _express.Request==="undefined"?Object:_express.Request,String])],AppController.prototype,"index",null);AppController=_ts_decorate([(0,_common.Controller)(),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[typeof _allianceinternalnodeutilities.LoggerService==="undefined"?Object:_allianceinternalnodeutilities.LoggerService,typeof _config.ConfigService==="undefined"?Object:_config.ConfigService,typeof _axios.HttpService==="undefined"?Object:_axios.HttpService,typeof _terminus.HealthCheckService==="undefined"?Object:_terminus.HealthCheckService,typeof _allianceinternalnodeutilities.RedisHealthIndicator==="undefined"?Object:_allianceinternalnodeutilities.RedisHealthIndicator])],AppController);return AppController}var GlobalFrameworkVariables;(function(GlobalFrameworkVariables){GlobalFrameworkVariables["RuntimeRootUrl"]="__ALLIANCE_RUNTIME_ROOT_URL";GlobalFrameworkVariables["Workspace"]="__ALLIANCE_WORKSPACE";GlobalFrameworkVariables["Customer"]="__ALLIANCE_CUSTOMER"})(GlobalFrameworkVariables||(GlobalFrameworkVariables={}));const loader=`
2
24
  <style>
3
25
  .alliance-portal-loader-wrapper {
4
26
  position: fixed;
@@ -104,32 +126,7 @@
104
126
  <div></div>
105
127
  </div>
106
128
  </div>
107
- `;function rootUrl(workspaceSlug,customerSlug){if(customerSlug){return`/${customerSlug}/${workspaceSlug}`}return`/${workspaceSlug}`}function portalBody({distribution,customerSlug,workspaceSlug}){const runtimeVariableScript=`
108
- <script>
109
- const { origin, pathname } = window.location;
110
-
111
- window.__ALLIANCE_RUNTIME_ROOT_URL = origin + '${rootUrl(workspaceSlug,customerSlug)}';
112
- window.__ALLIANCE_WORKSPACE = '${workspaceSlug}';
113
- window.__ALLIANCE_CUSTOMER = ${customerSlug?`'${customerSlug}'`:"undefined"};
114
- </script>
115
- `;return`
116
- ${runtimeVariableScript}
117
- <script>
118
- /* WEBPROVISIONS */
119
- !function(e,n){var o=n||{},c=document,t=window,s=function(n,o){e+=(e.indexOf("?")>-1?"&":"?")+encodeURIComponent(n)+"="
120
- +encodeURIComponent(o)},i=/[?&]{1}(wp[^=]*)=([^&#]*)/g,r=c.getElementsByTagName("script")[0],p=c.createElement("script");p.type="module";e=e+"/index.js";
121
- for(t.webprovisions=t.webprovisions||{_c:[],configure:function(){t.webprovisions._c.push(arguments)}};matches=i.exec(t.location.search);)
122
- s(matches[1],matches[2]);Object.keys(o).forEach((function(e){s("wp-"+e,o[e])})),p.async=!0,p.src=e,r.parentNode.insertBefore(p,r)}
123
- /**
124
- * Configure the implementation by specifying a remote endpoint with optional arguments.
125
- * url - The url to the remote endpoint for the implementation.
126
- * args - Object containing optional arguments for the implementation.
127
- */
128
- ("${distribution.url}", ${JSON.stringify(distribution.opts)})
129
- </script>
130
-
131
- ${loader}
132
- `}function unauthorizedPortalBody(){return`
129
+ `;function unauthorizedPortalBody(){return`
133
130
  <div class="unauthorized">
134
131
  <h1>401</h1>
135
132
  <p>You don't have permission to access this workspace.</p>
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});const _axios=require("@nestjs/axios");const _config=require("@nestjs/config");const _terminus=require("@nestjs/terminus");const _testing=require("@nestjs/testing");const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");const _vitest=require("vitest");const _config1=require("./config");function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap;var cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interop_require_wildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj}}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj)}var newObj={__proto__:null};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc)}else{newObj[key]=obj[key]}}}newObj.default=obj;if(cache){cache.set(obj,newObj)}return newObj}_vitest.vi.mock("graphql-request",async()=>{return{request:_vitest.vi.fn().mockImplementation(async(_1,_2,{objectId})=>{if(objectId==="has-access"){return{user:{id:objectId}}}return})}});(0,_vitest.describe)("AppController",()=>{const cfg={[_config1.ConfigKeys.AuthAuthority]:"test authority",[_config1.ConfigKeys.AuthClientSecret]:"test client secret",[_config1.ConfigKeys.AuthClientId]:"test client id",[_config1.ConfigKeys.ServiceBaseUrl]:"http://base-url",[_config1.ConfigKeys.WebprovisionsDistributionUrl]:"http://localhost:1234/distribution",[_config1.ConfigKeys.WebprovisionsDistributionCookiePolicyUrl]:"http://localhost:1234/cookie-policy.html",[_config1.ConfigKeys.WebprovisionsTag]:"the-tag",[_allianceinternalnodeutilities.SharedConfigKeys.DbEndpoint]:"http://localhost:1234/mocked-db"};let mock;async function setupMock(override={}){_vitest.vi.unstubAllEnvs();const{GlobalFrameworkVariables,createAppController}=await Promise.resolve().then(()=>_interop_require_wildcard(require("./app.controller")));for(const[key,value]of Object.entries({...cfg,...override})){if(value){_vitest.vi.stubEnv(key,value.toString())}}const AppController=createAppController();const module=await _testing.Test.createTestingModule({controllers:[AppController],providers:[_allianceinternalnodeutilities.RedisHealthIndicator],imports:[_config.ConfigModule.forRoot({isGlobal:true,validate:_config1.zConfig.parse,ignoreEnvFile:true}),_terminus.TerminusModule,_allianceinternalnodeutilities.LoggerModule.forRoot(),_axios.HttpModule]}).compile();return{ctrl:module.get(AppController),module,GlobalFrameworkVariables}}(0,_vitest.beforeEach)(async()=>{mock=await setupMock()});(0,_vitest.afterEach)(async()=>{await mock.module.close()});(0,_vitest.it)("defines ctrl",()=>{(0,_vitest.expect)(mock.ctrl).toBeDefined()});(0,_vitest.describe)("cookiePolicy",()=>{(0,_vitest.it)("fetches using configured cookie policy url",async()=>{const http=mock.module.get(_axios.HttpService);const spy=_vitest.vi.spyOn(http.axiosRef,"get").mockResolvedValue({});await mock.ctrl.cookiePolicy();(0,_vitest.expect)(spy).toHaveBeenCalledWith("http://localhost:1234/cookie-policy.html")});(0,_vitest.it)("fetches using {WEBPROVISIONS_DISTRIBUTION_URL}/cookie-policy.html by default",async()=>{mock=await setupMock({[_config1.ConfigKeys.WebprovisionsDistributionCookiePolicyUrl]:undefined});const http=mock.module.get(_axios.HttpService);const spy=_vitest.vi.spyOn(http.axiosRef,"get").mockResolvedValue({});await mock.ctrl.cookiePolicy();(0,_vitest.expect)(spy).toHaveBeenCalledWith("http://localhost:1234/distribution/cookie-policy.html")})});(0,_vitest.describe)("health",()=>{(0,_vitest.it)("it calls health service check",async()=>{const health=mock.module.get(_terminus.HealthCheckService);const spy=_vitest.vi.spyOn(health,"check").mockResolvedValue({status:"ok",details:{}});await mock.ctrl.health();(0,_vitest.expect)(spy).toHaveBeenCalled()})});(0,_vitest.describe)("index",async()=>{function mockReq({objectId,query={}}){return{oidc:{user:{sub:objectId}},query}}(0,_vitest.afterEach)(()=>{_vitest.vi.clearAllMocks()});(0,_vitest.it)("calls graphql",async()=>{const{request}=await Promise.resolve().then(()=>_interop_require_wildcard(require("graphql-request")));await mock.ctrl.index(mockReq({objectId:"guid"}),"system");(0,_vitest.expect)(request).toHaveBeenCalledOnce();const[dbEndpoint,_,queryArgs]=request.mock.lastCall;(0,_vitest.expect)(dbEndpoint).toBe("http://localhost:1234/mocked-db");(0,_vitest.expect)(queryArgs).toEqual({objectId:"guid",workspaceSlug:"system"})});(0,_vitest.describe)("portal html",()=>{(0,_vitest.it)("returns portal for authorized user",async()=>{const result=await mock.ctrl.index(mockReq({objectId:"has-access"}),"");(0,_vitest.expect)(result).toContain("http://localhost:1234/distribution")});(0,_vitest.it)("returns unauthorized for unauthorized user",async()=>{const result=await mock.ctrl.index(mockReq({objectId:"does-not-have-access"}),"");(0,_vitest.expect)(result).toContain("unauthorized");(0,_vitest.expect)(result).toContain(401)});(0,_vitest.describe)("global framework variables",()=>{(0,_vitest.it)("sets correct variables with default config",async()=>{const result=await mock.ctrl.index(mockReq({objectId:"has-access"}),"the-workspace");(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.RuntimeRootUrl} = window.origin + '/the-workspace';`);(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.Workspace} = 'the-workspace';`);(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.Customer} = undefined;`)});(0,_vitest.it)("sets correct variables with workspace specified",async()=>{mock=await setupMock({[_config1.ConfigKeys.Workspace]:"static-ws"});const result=await mock.ctrl.index(mockReq({objectId:"has-access"}),"the-workspace");(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.RuntimeRootUrl} = window.origin + '/static-ws';`);(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.Workspace} = 'static-ws';`);(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.Customer} = undefined;`)});(0,_vitest.it)("sets correct variables with customer and workspace specified",async()=>{mock=await setupMock({[_config1.ConfigKeys.Customer]:"static-customer",[_config1.ConfigKeys.Workspace]:"static-ws"});const result=await mock.ctrl.index(mockReq({objectId:"has-access"}),"the-workspace");(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.RuntimeRootUrl} = window.origin + '/static-customer/static-ws';`);(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.Workspace} = 'static-ws';`);(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.Customer} = 'static-customer';`)});(0,_vitest.it)("sets correct variables with origin as root specified",async()=>{mock=await setupMock({[_config1.ConfigKeys.Customer]:"static-customer",[_config1.ConfigKeys.Workspace]:"static-ws",[_config1.ConfigKeys.OriginAsRootUrl]:true});const result=await mock.ctrl.index(mockReq({objectId:"has-access"}),"the-workspace");(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.RuntimeRootUrl} = window.origin;`);(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.Workspace} = 'static-ws';`);(0,_vitest.expect)(result).toContain(`window.${mock.GlobalFrameworkVariables.Customer} = 'static-customer';`)})})});(0,_vitest.describe)("webprovisions tags",()=>{(0,_vitest.it)("adds webprovisions tag if configured",async()=>{const result=await mock.ctrl.index(mockReq({objectId:"has-access"}),"");(0,_vitest.expect)(result).toContain('{"tag":"the-tag"}')});(0,_vitest.it)("does not add webprovisions tag if not configured",async()=>{mock=await setupMock({[_config1.ConfigKeys.WebprovisionsTag]:undefined});const result=await mock.ctrl.index(mockReq({objectId:"has-access"}),"");(0,_vitest.expect)(result).toContain("{}")});(0,_vitest.it)("does not add configured webprovisions tag when wp query strings are present",async()=>{const withTagQuery=await mock.ctrl.index(mockReq({objectId:"has-access",query:{"wp-tag":"some-tag"}}),"");(0,_vitest.expect)(withTagQuery).not.toContain('{"tag":"the-tag"}');const withVersionQuery=await mock.ctrl.index(mockReq({objectId:"has-access",query:{"wp-version":"some-version"}}),"");(0,_vitest.expect)(withVersionQuery).not.toContain('{"tag":"the-tag"}')})})})});
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"AppModule",{enumerable:true,get:function(){return AppModule}});const _axios=require("@nestjs/axios");const _common=require("@nestjs/common");const _config=require("@nestjs/config");const _terminus=require("@nestjs/terminus");const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");const _appcontroller=require("./app.controller");function _ts_decorate(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect==="object"&&typeof Reflect.decorate==="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)if(d=decorators[i])r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r;return c>3&&r&&Object.defineProperty(target,key,r),r}let AppModule=class AppModule{};AppModule=_ts_decorate([(0,_common.Module)({controllers:[(0,_appcontroller.createAppController)({})],imports:[_config.ConfigModule.forRoot({isGlobal:true}),_terminus.TerminusModule,_allianceinternalnodeutilities.LoggerModule.forRoot(),_axios.HttpModule],exports:[],providers:[_allianceinternalnodeutilities.RedisHealthIndicator]})],AppModule);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"AppModule",{enumerable:true,get:function(){return AppModule}});const _axios=require("@nestjs/axios");const _common=require("@nestjs/common");const _config=require("@nestjs/config");const _terminus=require("@nestjs/terminus");const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");const _appcontroller=require("./app.controller");const _config1=require("./config");function _ts_decorate(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect==="object"&&typeof Reflect.decorate==="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)if(d=decorators[i])r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r;return c>3&&r&&Object.defineProperty(target,key,r),r}let AppModule=class AppModule{static forRoot(){return{module:AppModule,controllers:[(0,_appcontroller.createAppController)()],imports:[_config.ConfigModule.forRoot({isGlobal:true,validate:_config1.zConfig.parse}),_terminus.TerminusModule,_allianceinternalnodeutilities.LoggerModule.forRoot(),_axios.HttpModule],exports:[],providers:[_allianceinternalnodeutilities.RedisHealthIndicator]}}};AppModule=_ts_decorate([(0,_common.Module)({})],AppModule);
package/dist/auth.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"auth",{enumerable:true,get:function(){return auth}});const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");const _graphqlrequest=require("graphql-request");const _jose=require("jose");const _config=require("./config");const _graphql=require("./graphql");function auth(configService,logger){const middleware=(0,_allianceinternalnodeutilities.authMiddleware)(configService,{baseURL:configService.getOrThrow(_config.ConfigKeys.ServiceBaseUrl).replace("{{port}}",configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.ServicePort)),clientSecret:configService.getOrThrow(_config.ConfigKeys.AuthClientSecret),clientID:configService.getOrThrow(_config.ConfigKeys.AuthClientId),authorizationParams:{response_type:configService.getOrThrow(_config.ConfigKeys.AuthResponseType),scope:configService.getOrThrow(_config.ConfigKeys.AuthScopes)},sessionCookiePath:configService.get(_config.ConfigKeys.AuthCookiePath),issuerBaseURL:`${configService.getOrThrow(_config.ConfigKeys.AuthAuthority)}/.well-known/openid-configuration`,async afterCallback(_,__,session){const claims=(0,_jose.decodeJwt)(session.id_token);const user={displayName:claims.name||"Empty displayName",email:claims.email||claims.emails[0]||"Empty email",objectId:claims.sub||claims.oid};logger.trace("decoded JWT and mapped claims to user, getting or creating user in database",{claims,user});try{await (0,_graphqlrequest.request)(configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.DbEndpoint),_graphql.GetOrCreateUserDocument,{input:user},{authorization:(0,_allianceinternalnodeutilities.createSystemUserToken)(configService)});logger.trace("added user to database, if it did not already exist")}catch{}const skipGroupClaimCheck=configService.get(_config.ConfigKeys.AuthSkipGroupClaimCheck)==="true";if(!skipGroupClaimCheck){const type=hasEnterpriseAdminRole(claims)?"system-admin":"user";logger.trace("updating user type according to user claims",{type});try{await (0,_graphqlrequest.request)(configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.DbEndpoint),_graphql.SetUserTypeDocument,{input:{objectId:user.objectId,type}},{authorization:(0,_allianceinternalnodeutilities.createSystemUserToken)(configService)});logger.trace("user type updated")}catch{}}return session}});return(req,res,next)=>{if(req.url.startsWith("/health")){return next()}return middleware(req,res,next)}}function hasEnterpriseAdminRole(claims){if(!claims.groups){return false}const aceEnterpriseAdminRoleId="PROD_ACE_Enterprise_Admins";return claims.groups.includes(aceEnterpriseAdminRoleId)}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"auth",{enumerable:true,get:function(){return auth}});const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");const _graphqlrequest=require("graphql-request");const _jose=require("jose");const _config=require("./config");const _graphql=require("./graphql");function auth(configService,logger){const middleware=(0,_allianceinternalnodeutilities.authMiddleware)(configService,{baseURL:configService.getOrThrow(_config.ConfigKeys.ServiceBaseUrl).replace("{{port}}",configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.ServicePort)),clientSecret:configService.getOrThrow(_config.ConfigKeys.AuthClientSecret),clientID:configService.getOrThrow(_config.ConfigKeys.AuthClientId),authorizationParams:{response_type:configService.getOrThrow(_config.ConfigKeys.AuthResponseType),scope:configService.getOrThrow(_config.ConfigKeys.AuthScopes)},sessionCookiePath:configService.get(_config.ConfigKeys.AuthCookiePath),issuerBaseURL:`${configService.getOrThrow(_config.ConfigKeys.AuthAuthority)}/.well-known/openid-configuration`,async afterCallback(_,__,session){const claims=(0,_jose.decodeJwt)(session.id_token);const user={displayName:claims.name||"Empty displayName",email:claims.email||claims.emails[0]||"Empty email",objectId:claims.sub||claims.oid};logger.trace("decoded JWT and mapped claims to user, getting or creating user in database",{claims,user});try{await (0,_graphqlrequest.request)(configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.DbEndpoint),_graphql.GetOrCreateUserDocument,{input:user},{authorization:(0,_allianceinternalnodeutilities.createSystemUserToken)(configService)});logger.trace("added user to database, if it did not already exist")}catch{}if(!configService.get(_config.ConfigKeys.AuthSkipGroupClaimCheck)){const type=hasEnterpriseAdminRole(claims)?"system-admin":"user";logger.trace("updating user type according to user claims",{type});try{await (0,_graphqlrequest.request)(configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.DbEndpoint),_graphql.SetUserTypeDocument,{input:{objectId:user.objectId,type}},{authorization:(0,_allianceinternalnodeutilities.createSystemUserToken)(configService)});logger.trace("user type updated")}catch{}}return session}});return(req,res,next)=>{if(req.url.startsWith("/health")){return next()}return middleware(req,res,next)}}function hasEnterpriseAdminRole(claims){if(!claims.groups){return false}const aceEnterpriseAdminRoleId="PROD_ACE_Enterprise_Admins";return claims.groups.includes(aceEnterpriseAdminRoleId)}
package/dist/config.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"ConfigKeys",{enumerable:true,get:function(){return ConfigKeys}});var ConfigKeys;(function(ConfigKeys){ConfigKeys["AuthScopes"]="AUTH_SCOPES";ConfigKeys["AuthAuthority"]="AUTH_AUTHORITY";ConfigKeys["AuthClientSecret"]="AUTH_CLIENT_SECRET";ConfigKeys["AuthClientId"]="AUTH_CLIENT_ID";ConfigKeys["AuthResponseType"]="AUTH_RESPONSE_TYPE";ConfigKeys["AuthSkipGroupClaimCheck"]="AUTH_SKIP_GROUP_CLAIM_CHECK";ConfigKeys["AuthCookiePath"]="AUTH_COOKIE_PATH";ConfigKeys["ServiceBaseUrl"]="SERVICE_BASE_URL";ConfigKeys["WebprovisionsTag"]="WEBPROVISIONS_TAG";ConfigKeys["WebprovisionsDistributionUrl"]="WEBPROVISIONS_DISTRIBUTION_URL";ConfigKeys["WebprovisionsDistributionCookiePolicyUrl"]="WEBPROVISIONS_DISTRIBUTION_COOKIE_POLICY_URL"})(ConfigKeys||(ConfigKeys={}));
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});function _export(target,all){for(var name in all)Object.defineProperty(target,name,{enumerable:true,get:all[name]})}_export(exports,{ConfigKeys:function(){return ConfigKeys},zConfig:function(){return zConfig}});const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");var ConfigKeys;(function(ConfigKeys){ConfigKeys["AuthScopes"]="AUTH_SCOPES";ConfigKeys["AuthAuthority"]="AUTH_AUTHORITY";ConfigKeys["AuthClientSecret"]="AUTH_CLIENT_SECRET";ConfigKeys["AuthClientId"]="AUTH_CLIENT_ID";ConfigKeys["AuthResponseType"]="AUTH_RESPONSE_TYPE";ConfigKeys["AuthSkipGroupClaimCheck"]="AUTH_SKIP_GROUP_CLAIM_CHECK";ConfigKeys["AuthCookiePath"]="AUTH_COOKIE_PATH";ConfigKeys["ServiceBaseUrl"]="SERVICE_BASE_URL";ConfigKeys["WebprovisionsTag"]="WEBPROVISIONS_TAG";ConfigKeys["WebprovisionsDistributionUrl"]="WEBPROVISIONS_DISTRIBUTION_URL";ConfigKeys["WebprovisionsDistributionCookiePolicyUrl"]="WEBPROVISIONS_DISTRIBUTION_COOKIE_POLICY_URL";ConfigKeys["Customer"]="CUSTOMER";ConfigKeys["Workspace"]="WORKSPACE";ConfigKeys["OriginAsRootUrl"]="ORIGIN_AS_ROOT_URL"})(ConfigKeys||(ConfigKeys={}));const zConfig=_allianceinternalnodeutilities.zSharedConfig.extend({["AUTH_SCOPES"]:_allianceinternalnodeutilities.zNonEmptyString.default("openid"),["AUTH_AUTHORITY"]:_allianceinternalnodeutilities.zNonEmptyString,["AUTH_CLIENT_SECRET"]:_allianceinternalnodeutilities.zNonEmptyString,["AUTH_CLIENT_ID"]:_allianceinternalnodeutilities.zNonEmptyString,["AUTH_RESPONSE_TYPE"]:_allianceinternalnodeutilities.zNonEmptyString.default("code"),["AUTH_SKIP_GROUP_CLAIM_CHECK"]:_allianceinternalnodeutilities.zBooleanEnum.default("false"),["AUTH_COOKIE_PATH"]:_allianceinternalnodeutilities.zNonEmptyString.optional(),["SERVICE_BASE_URL"]:_allianceinternalnodeutilities.zNonEmptyString,["WEBPROVISIONS_TAG"]:_allianceinternalnodeutilities.zNonEmptyString.optional(),["WEBPROVISIONS_DISTRIBUTION_URL"]:_allianceinternalnodeutilities.zNonEmptyString,["WEBPROVISIONS_DISTRIBUTION_COOKIE_POLICY_URL"]:_allianceinternalnodeutilities.zNonEmptyString.optional(),["CUSTOMER"]:_allianceinternalnodeutilities.zNonEmptyString.optional(),["WORKSPACE"]:_allianceinternalnodeutilities.zNonEmptyString.optional(),["ORIGIN_AS_ROOT_URL"]:_allianceinternalnodeutilities.zBooleanEnum.default("false")});
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});const _config=require("@nestjs/config");const _core=require("@nestjs/core");const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");const _appmodule=require("./app.module");const _auth=require("./auth");async function startPortal(){const app=await _core.NestFactory.create(_appmodule.AppModule,{bufferLogs:true});const configService=app.get(_config.ConfigService);const logger=await app.resolve(_allianceinternalnodeutilities.LoggerService);app.useLogger(logger);app.flushLogs();app.use((0,_auth.auth)(configService,logger));app.useGlobalInterceptors(new _allianceinternalnodeutilities.LoggerErrorInterceptor);app.useGlobalFilters(new _allianceinternalnodeutilities.AllianceExceptionFilter);await app.listen(configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.ServicePort))}startPortal();
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});const _config=require("@nestjs/config");const _core=require("@nestjs/core");const _allianceinternalnodeutilities=require("@telia-ace/alliance-internal-node-utilities");const _dotenv=require("dotenv");const _appmodule=require("./app.module");const _auth=require("./auth");(0,_dotenv.config)();async function startPortal(){const app=await _core.NestFactory.create(_appmodule.AppModule.forRoot(),{bufferLogs:true});const configService=app.get(_config.ConfigService);const logger=await app.resolve(_allianceinternalnodeutilities.LoggerService);app.useLogger(logger);app.flushLogs();app.use((0,_auth.auth)(configService,logger));app.useGlobalInterceptors(new _allianceinternalnodeutilities.LoggerErrorInterceptor);app.useGlobalFilters(new _allianceinternalnodeutilities.AllianceExceptionFilter);await app.listen(configService.getOrThrow(_allianceinternalnodeutilities.SharedConfigKeys.ServicePort))}startPortal();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telia-ace/alliance-portal",
3
- "version": "1.0.7-next.2",
3
+ "version": "1.0.7-next.4",
4
4
  "description": "ACE Alliance portal",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "author": "Telia Company AB",
@@ -18,14 +18,16 @@
18
18
  "@nestjs/config": "^3.1.1",
19
19
  "@nestjs/core": "^10.2.7",
20
20
  "@nestjs/platform-express": "^10.2.7",
21
- "@telia-ace/alliance-internal-node-utilities": "1.0.4-next.2",
21
+ "@nestjs/terminus": "^10.1.1",
22
+ "@telia-ace/alliance-internal-node-utilities": "1.0.4-next.3",
23
+ "dotenv": "^16.3.1",
22
24
  "express": "^4.18.2",
23
25
  "graphql": "^16.8.1",
24
26
  "graphql-request": "^6.1.0",
25
27
  "jose": "^4.15.3",
26
28
  "reflect-metadata": "^0.1.13",
27
- "@nestjs/terminus": "^10.1.1",
28
- "rxjs": "^7.8.1"
29
+ "rxjs": "^7.8.1",
30
+ "zod": "^3.22.4"
29
31
  },
30
32
  "devDependencies": {
31
33
  "@graphql-codegen/cli": "^5.0.0",
@@ -33,11 +35,13 @@
33
35
  "@graphql-codegen/typescript-operations": "^4.0.1",
34
36
  "@graphql-typed-document-node/core": "^3.2.0",
35
37
  "@nestjs/cli": "^10.1.18",
38
+ "@nestjs/testing": "^10.2.7",
36
39
  "@swc/cli": "^0.1.62",
37
40
  "@swc/core": "^1.3.93",
38
41
  "@types/express": "^4.17.19",
39
42
  "@types/node": "^20.8.5",
40
- "tsup": "^7.2.0"
43
+ "unplugin-swc": "^1.4.3",
44
+ "vitest": "^0.34.6"
41
45
  },
42
46
  "publishConfig": {
43
47
  "access": "public"
@@ -46,6 +50,7 @@
46
50
  "dev": "nest start --watch",
47
51
  "build:dev": "nest build",
48
52
  "build:prod": "nest build",
53
+ "test": "vitest",
49
54
  "start": "node dist/index",
50
55
  "generate": "graphql-codegen"
51
56
  }