Skip to content

Commit

Permalink
feat: BrowZer error page (#180)
Browse files Browse the repository at this point in the history
  • Loading branch information
rentallect authored Aug 4, 2023
1 parent f7f0b0d commit 9565689
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 21 deletions.
7 changes: 7 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ const ZBR_CONSTANTS =
AZURE_AD_URL_REGEX: /login\.microsoftonline\.com/,
AZURE_AD_SCOPES: ['User.Read', 'openid', 'email'],

ZBR_ERROR_CODE_INVALID_AUTH: 1001,
ZBR_ERROR_CODE_CONTROLLER_REQ_FAIL: 1002,
ZBR_ERROR_CODE_SERVICE_NOT_IN_LIST: 1003,
ZBR_ERROR_CODE_SERVICE_UNREACHABLE: 1004,
ZBR_ERROR_CODE_SERVICE_HAS_NO_CONFIG: 1005,
ZBR_ERROR_CODE_UNSUPPORTED_BROWSER: 1006,

};


Expand Down
74 changes: 53 additions & 21 deletions src/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { Auth0Client } from '@auth0/auth0-spa-js';
import Bowser from 'bowser';
import uPlot from 'uplot';
import * as msal from '@azure/msal-browser';
import { stringify } from './urlon';


/**
Expand Down Expand Up @@ -186,8 +187,12 @@ class ZitiBrowzerRuntime {

let errStr = `The browser you are using:\n\n${this.ua.browser.name} v${this.ua.browser.version}\n\nis currently unsupported by\nOpenZiti BrowZer Runtime v${_options.version}.`;

alert(errStr);
throw new Error(errStr);
this.browzer_error({
status: 409,
code: ZBR_CONSTANTS.ZBR_ERROR_CODE_UNSUPPORTED_BROWSER,
title: `The browser you are using is: ${this.ua.browser.name} v${this.ua.browser.version}.`,
message: `This browser is currently unsupported by BrowZer Runtime v${_options.version}.`
});

}

Expand Down Expand Up @@ -841,13 +846,26 @@ class ZitiBrowzerRuntime {
}
}

browzer_error( browzer_error_data_json ) {

setTimeout(function() {
window.location.href = `
${zitiBrowzerRuntime.zitiConfig.browzer.bootstrapper.self.scheme}://${zitiBrowzerRuntime.zitiConfig.browzer.bootstrapper.self.host}:${zitiBrowzerRuntime.zitiConfig.browzer.bootstrapper.self.port}/browzer_error?browzer_error_data=${stringify(JSON.stringify(browzer_error_data_json))}
`;
}, 10);

}

noConfigForServiceEventHandler(noConfigForServiceEvent) {

this.logger.trace(`noConfigForServiceEventHandler() `, noConfigForServiceEvent);

let errStr = `Ziti Service [${noConfigForServiceEvent.serviceName}] has no associated configs.\n\nContact your Ziti Network admin.`;

alert(errStr);
window.zitiBrowzerRuntime.browzer_error({
status: 409,
code: ZBR_CONSTANTS.ZBR_ERROR_CODE_SERVICE_HAS_NO_CONFIG,
title: `Ziti Service [${noConfigForServiceEvent.serviceName}] has no associated configs.`,
message: `Possible network configuration issue exists.`
});

}

Expand Down Expand Up @@ -898,52 +916,66 @@ class ZitiBrowzerRuntime {
return showOccurrences ? found : found[0];
};


let cm = closestMatch(noServiceEvent.serviceName, noServiceEvent.serviceList, true);

let errStr = `Ziti Service [${noServiceEvent.serviceName}] not found in list of Services your Identity can access -- closest match [${cm}].\n\nContact your Ziti Network admin.`;

alert(errStr);
window.zitiBrowzerRuntime.browzer_error({
status: 409,
code: ZBR_CONSTANTS.ZBR_ERROR_CODE_SERVICE_NOT_IN_LIST,
title: `Ziti Service [${noServiceEvent.serviceName}] not found in list of Services your Identity can access.`,
message: `Closest match [${cm}] -- Possible network configuration issue exists.`
});

}

sessionCreationErrorEventHandler(sessionCreationErrorEvent) {

this.logger.trace(`sessionCreationErrorEventHandler() `, sessionCreationErrorEvent);

let errStr = `Ziti Service [${window.zitiBrowzerRuntime.zitiConfig.browzer.bootstrapper.target.service}] cannot be reached -- [${sessionCreationErrorEvent.error}].\n\nContact your Ziti Network admin.`;

alert(errStr);
window.zitiBrowzerRuntime.browzer_error({
status: 409,
code: ZBR_CONSTANTS.ZBR_ERROR_CODE_SERVICE_UNREACHABLE,
title: `Ziti Service '${window.zitiBrowzerRuntime.zitiConfig.browzer.bootstrapper.target.service}' cannot be reached -- [${sessionCreationErrorEvent.error}]`,
message: `The request conflicts with the current state of the network.`
});

}

invalidAuthEventHandler(invalidAuthEvent) {

this.logger.trace(`invalidAuthEventHandler() `, invalidAuthEvent);

let errStr = `User [${invalidAuthEvent.email}] cannot be authenticated onto Ziti Network.\n\nContact your Ziti Network admin.`;

alert(errStr);
window.zitiBrowzerRuntime.browzer_error({
status: 511,
code: ZBR_CONSTANTS.ZBR_ERROR_CODE_INVALID_AUTH,
title: `User '${invalidAuthEvent.email}' cannot be authenticated onto Ziti Network`,
message: `The client needs to authenticate to gain network access.`
});

}

channelConnectFailEventHandler(channelConnectFailEvent) {

this.logger.trace(`channelConnectFailEventHandler() `, channelConnectFailEvent);

let errStr = `Service [${channelConnectFailEvent.serviceName}] connect attempt failed on Ziti Network. Is the web server up?\n\nContact your Ziti Network admin.`;

alert(errStr);
window.zitiBrowzerRuntime.browzer_error({
status: 409,
code: ZBR_CONSTANTS.ZBR_ERROR_CODE_SERVICE_UNREACHABLE,
title: `Ziti Service '${channelConnectFailEvent.serviceName}' connect attempt failed on Ziti Network.`,
message: `The web server might be down.`
});

}

requestFailedWithNoResponseEventHandler(requestFailedWithNoResponseEvent) {

this.logger.trace(`requestFailedWithNoResponseEventHandler() `, requestFailedWithNoResponseEvent);

let errStr = `HTTP Request to [${requestFailedWithNoResponseEvent.url}] failed - possible server-side certificate issue exists.\n\nContact your Ziti Network admin.`;

alert(errStr);
window.zitiBrowzerRuntime.browzer_error({
status: 503,
code: ZBR_CONSTANTS.ZBR_ERROR_CODE_CONTROLLER_REQ_FAIL,
title: `HTTP Request to [${requestFailedWithNoResponseEvent.url}] failed.`,
message: `Possible server-side certificate issue exists.`
});

}

Expand Down
146 changes: 146 additions & 0 deletions src/urlon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
'use strict'

var keyStringifyRegexp = /([=:@$/])/g
var valueStringifyRegexp = /([&;/])/g
var keyParseRegexp = /[=:@$]/
var valueParseRegexp = /[&;]/

function encodeString(str, regexp) {
return encodeURI(str.replace(regexp, '/$1'))
}

function trim(res) {
return typeof res === 'string' ? res.replace(/;+$/g, '') : res
}

function stringify(input, recursive) {
if (!recursive) {
return trim(stringify(input, true))
}
// Number, Boolean or Null
if (
typeof input === 'number' ||
input === true ||
input === false ||
input === null
) {
return ':' + input
}
var res = []
// Array
if (input instanceof Array) {
for (var i = 0; i < input.length; ++i) {
typeof input[i] === 'undefined'
? res.push(':null')
: res.push(stringify(input[i], true))
}
return '@' + res.join('&') + ';'
}
// Object
if (typeof input === 'object') {
for (var key in input) {
var val = stringify(input[key], true)
if (val) {
res.push(encodeString(key, keyStringifyRegexp) + val)
}
}
return '$' + res.join('&') + ';'
}
// undefined
if (typeof input === 'undefined') {
return
}
// String
return '=' + encodeString(input.toString(), valueStringifyRegexp)
}

function parse(str) {
var pos = 0
str = decodeURI(str)

function readToken(regexp) {
var token = ''
for (; pos !== str.length; ++pos) {
if (str.charAt(pos) === '/') {
pos += 1
if (pos === str.length) {
token += ';'
break
}
} else if (str.charAt(pos).match(regexp)) {
break
}
token += str.charAt(pos)
}
return token
}

function parseToken() {
var type = str.charAt(pos++)
// String
if (type === '=') {
return readToken(valueParseRegexp)
}
// Number, Boolean or Null
if (type === ':') {
var value = readToken(valueParseRegexp)
if (value === 'true') {
return true
}
if (value === 'false') {
return false
}
value = parseFloat(value)
return isNaN(value) ? null : value
}
var res
// Array
if (type === '@') {
res = []
loop: {
// empty array
if (pos >= str.length || str.charAt(pos) === ';') {
break loop
}
// parse array items
while (1) {
res.push(parseToken())
if (pos >= str.length || str.charAt(pos) === ';') {
break loop
}
pos += 1
}
}
pos += 1
return res
}
// Object
if (type === '$') {
res = {}
loop: {
if (pos >= str.length || str.charAt(pos) === ';') {
break loop
}
while (1) {
var name = readToken(keyParseRegexp)
res[name] = parseToken()
if (pos >= str.length || str.charAt(pos) === ';') {
break loop
}
pos += 1
}
}
pos += 1
return res
}
// Error
throw new Error('Unexpected char ' + type)
}

return parseToken()
}

export {
stringify,
parse,
};

0 comments on commit 9565689

Please sign in to comment.