@cortezaproject/corteza-vue 2021.9.7 → 2021.9.8
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/components/c3/C3.d.ts +5 -0
- package/dist/components/input/CInputDateTime/lib/index.d.ts +4 -4
- package/dist/components/itemPicker/C3.d.ts +1 -0
- package/dist/components/itemPicker/CItemPicker.c3.d.ts +32 -0
- package/dist/components/itemPicker/index.d.ts +1 -1
- package/dist/components/reporter/index.d.ts +4 -0
- package/dist/index.es.js +118 -37
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +118 -37
- package/dist/index.js.map +1 -1
- package/dist/libs/filter.d.ts +3 -1
- package/dist/plugins/auth.d.ts +34 -5
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function getDate(value: string): string | undefined;
|
|
2
|
-
export declare function getTime(value: string): string | undefined;
|
|
3
|
-
export declare function setDate(date: string, value: string, noDate?: boolean, noTime?: boolean): string | undefined;
|
|
4
|
-
export declare function setTime(time: string, value: string, noDate?: boolean, noTime?: boolean): string | undefined;
|
|
1
|
+
export declare function getDate(value: string | undefined): string | undefined;
|
|
2
|
+
export declare function getTime(value: string | undefined): string | undefined;
|
|
3
|
+
export declare function setDate(date: string | undefined, value: string | undefined, noDate?: boolean, noTime?: boolean): string | undefined;
|
|
4
|
+
export declare function setTime(time: string | undefined, value: string | undefined, noDate?: boolean, noTime?: boolean): string | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CItemPicker } from "./CItemPicker.c3";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/// <reference path="../../src/vue.shims.d.ts" />
|
|
2
|
+
declare namespace _default {
|
|
3
|
+
export const name: string;
|
|
4
|
+
export const group: string[];
|
|
5
|
+
export { component };
|
|
6
|
+
export { props };
|
|
7
|
+
export const controls: any[];
|
|
8
|
+
}
|
|
9
|
+
export default _default;
|
|
10
|
+
import { default as component } from "*.vue";
|
|
11
|
+
declare namespace props {
|
|
12
|
+
export const options: {
|
|
13
|
+
value: string;
|
|
14
|
+
text: string;
|
|
15
|
+
}[];
|
|
16
|
+
export const value: string[];
|
|
17
|
+
export namespace labels {
|
|
18
|
+
export const searchPlaceholder: string;
|
|
19
|
+
export const availableItems: string;
|
|
20
|
+
export const selectAllItems: string;
|
|
21
|
+
export const selectedItems: string;
|
|
22
|
+
export const systemItem: string;
|
|
23
|
+
export const unselectAllItems: string;
|
|
24
|
+
export const noItemsFound: string;
|
|
25
|
+
}
|
|
26
|
+
export const hideFilter: boolean;
|
|
27
|
+
export const hideIcons: boolean;
|
|
28
|
+
export const disabled: boolean;
|
|
29
|
+
export const disabledFilter: boolean;
|
|
30
|
+
export const disabledSorting: boolean;
|
|
31
|
+
export const disabledDragging: boolean;
|
|
32
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as CItemPicker } from './CItemPicker.vue';
|
|
2
|
-
export { default as
|
|
2
|
+
export { default as CItemPickerItem } from './CItemPickerItem.vue';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { default as CReportChart } from './Viewers/CReportChart.vue';
|
|
2
|
+
export { default as CReportMetric } from './Viewers/CReportMetric.vue';
|
|
3
|
+
export { default as CReportTable } from './Viewers/CReportTable.vue';
|
|
4
|
+
export { default as CReportText } from './Viewers/CReportText.vue';
|
package/dist/index.es.js
CHANGED
|
@@ -1920,15 +1920,19 @@ var url = /*#__PURE__*/Object.freeze({
|
|
|
1920
1920
|
const accessToken = Symbol('accessToken');
|
|
1921
1921
|
const user = Symbol('user');
|
|
1922
1922
|
/**
|
|
1923
|
-
* This is an endpoint of
|
|
1923
|
+
* This is an endpoint of an oauth2 authorization-code flow + refresh token exchange
|
|
1924
1924
|
* for default client.
|
|
1925
1925
|
*
|
|
1926
|
-
* If you are concerned about security, this is not much different
|
|
1926
|
+
* If you are concerned about security, this is not much different to using a dedicated backend
|
|
1927
1927
|
* for this SPA that only redirects to a set of allowed URIs.
|
|
1928
1928
|
*/
|
|
1929
1929
|
const oauth2FlowURL = '/oauth2/default-client';
|
|
1930
1930
|
const oauth2InfoURL = '/oauth2/info';
|
|
1931
1931
|
const oauth2Scope = 'profile api';
|
|
1932
|
+
const storeKeyFlowStarted = 'auth.flow-started';
|
|
1933
|
+
const storeKeyFinalState = 'auth.state.final';
|
|
1934
|
+
const storeKeyRefreshToken = 'auth.refresh-token';
|
|
1935
|
+
const maxStartAttempts = 5;
|
|
1932
1936
|
class Auth {
|
|
1933
1937
|
constructor({ app, verbose, cortezaAuthURL, callbackURL, entrypointURL, location, sessionStorage, refreshFactor }) {
|
|
1934
1938
|
if (refreshFactor >= 1 || refreshFactor <= 0) {
|
|
@@ -1971,13 +1975,6 @@ class Auth {
|
|
|
1971
1975
|
error: noop,
|
|
1972
1976
|
};
|
|
1973
1977
|
}
|
|
1974
|
-
/**
|
|
1975
|
-
* Returns prefixed key
|
|
1976
|
-
* @param key
|
|
1977
|
-
*/
|
|
1978
|
-
get refreshTokenKey() {
|
|
1979
|
-
return 'auth.refresh-token';
|
|
1980
|
-
}
|
|
1981
1978
|
/**
|
|
1982
1979
|
* Returns function that returns current access token
|
|
1983
1980
|
*/
|
|
@@ -2001,43 +1998,83 @@ class Auth {
|
|
|
2001
1998
|
handle(req = new URL(this.entrypointURL)) {
|
|
2002
1999
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2003
2000
|
this.log.info('handling authentication');
|
|
2004
|
-
if (
|
|
2001
|
+
if (this.isCallback(req.pathname)) {
|
|
2005
2002
|
this.log.info('handling authentication callback');
|
|
2006
2003
|
const params = new URLSearchParams(req.search);
|
|
2007
2004
|
if (params.has('error')) {
|
|
2008
2005
|
throw new Error(params.get('error') || 'authentication flow failed with error');
|
|
2009
2006
|
}
|
|
2010
2007
|
if (params.has('code')) {
|
|
2011
|
-
let finalLocation =
|
|
2008
|
+
let finalLocation = this.entrypointURL;
|
|
2012
2009
|
if (params.has('state')) {
|
|
2013
2010
|
const state = params.get('state') || '';
|
|
2014
|
-
const
|
|
2015
|
-
this.
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2011
|
+
const storeKeyStateLocation = `auth.state.${state}.location`;
|
|
2012
|
+
const tmp = this.sessionStorage.getItem(storeKeyStateLocation);
|
|
2013
|
+
if (tmp === null) {
|
|
2014
|
+
console.warn('state does not match, restarting authentication flow');
|
|
2015
|
+
this.startAuthenticationFlow();
|
|
2016
|
+
return null;
|
|
2019
2017
|
}
|
|
2020
|
-
if (
|
|
2018
|
+
if (!this.isCallback(tmp)) {
|
|
2021
2019
|
// if by some coincidence we got callback URL to finalLocation
|
|
2022
|
-
// we'll silently ignore it
|
|
2023
|
-
finalLocation =
|
|
2024
|
-
}
|
|
2025
|
-
else {
|
|
2026
|
-
this.log.info('location before auth flow start', finalLocation);
|
|
2020
|
+
// we'll silently ignore it and redirect user back to entrypoint
|
|
2021
|
+
finalLocation = tmp;
|
|
2027
2022
|
}
|
|
2028
|
-
this.sessionStorage.removeItem(
|
|
2023
|
+
this.sessionStorage.removeItem(storeKeyStateLocation);
|
|
2029
2024
|
}
|
|
2030
2025
|
const code = params.get('code') || '';
|
|
2031
2026
|
this.log.info('authorization code received', code);
|
|
2032
|
-
yield this.exchangeCode(code);
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
}
|
|
2027
|
+
const rsp = yield this.exchangeCode(code);
|
|
2028
|
+
this.startFinalState(finalLocation);
|
|
2029
|
+
return rsp;
|
|
2036
2030
|
}
|
|
2037
2031
|
}
|
|
2038
2032
|
return this.check();
|
|
2039
2033
|
});
|
|
2040
2034
|
}
|
|
2035
|
+
/**
|
|
2036
|
+
* Flagging session storage
|
|
2037
|
+
*
|
|
2038
|
+
* Challenge with sessions and browser tabs:
|
|
2039
|
+
* Each browser tab & window interacts with an isolated session. When user clicks on a link to and wants to open
|
|
2040
|
+
* it in a new window or a tab, or when tab is duplicated, session contents are copied!
|
|
2041
|
+
*
|
|
2042
|
+
* Consequences of that are that two (or more) tabs end up with the same session
|
|
2043
|
+
* and the same refresh token, and we need to detect if we're dealing with refresh token in an old or new session.
|
|
2044
|
+
*
|
|
2045
|
+
* With this function we start the final state and flag the session. This way we'll
|
|
2046
|
+
* know, after the redirection to the final location, if this is a final stage or not and if the refresh token
|
|
2047
|
+
* belongs to this session or not.
|
|
2048
|
+
*/
|
|
2049
|
+
startFinalState(dst) {
|
|
2050
|
+
this.log.info('redirecting back to final destination', dst);
|
|
2051
|
+
this.sessionStorage.setItem(storeKeyFinalState, Date.now().toString());
|
|
2052
|
+
this.location.assign(dst);
|
|
2053
|
+
}
|
|
2054
|
+
/**
|
|
2055
|
+
* Called when refresh token is re-fetched.
|
|
2056
|
+
*
|
|
2057
|
+
* Cleanup aux items in the session store
|
|
2058
|
+
*/
|
|
2059
|
+
completeFinalState() {
|
|
2060
|
+
this.sessionStorage.removeItem(storeKeyFinalState);
|
|
2061
|
+
this.sessionStorage.removeItem(storeKeyFlowStarted);
|
|
2062
|
+
const stateKey = /^auth\.state\.\w+\.location$/;
|
|
2063
|
+
for (let i = 0; i < this.sessionStorage.length; i++) {
|
|
2064
|
+
const key = this.sessionStorage.key(i);
|
|
2065
|
+
if (key !== null && stateKey.test(key)) {
|
|
2066
|
+
this.sessionStorage.removeItem(key);
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
/**
|
|
2071
|
+
* Are we in a final state or not?
|
|
2072
|
+
*
|
|
2073
|
+
* See startFinalState function for more details
|
|
2074
|
+
*/
|
|
2075
|
+
inFinalState() {
|
|
2076
|
+
return this.sessionStorage.getItem(storeKeyFinalState) !== null;
|
|
2077
|
+
}
|
|
2041
2078
|
/**
|
|
2042
2079
|
* Checks current auth state; is access token loaded OR do we have a refresh token we can use
|
|
2043
2080
|
*
|
|
@@ -2071,27 +2108,34 @@ class Auth {
|
|
|
2071
2108
|
this[user] = authUser;
|
|
2072
2109
|
return data;
|
|
2073
2110
|
}).catch((error) => {
|
|
2074
|
-
this.log.
|
|
2111
|
+
this.log.error('data fetch form info endpoint failed', { oauth2InfoURL, headers, error });
|
|
2075
2112
|
// assume invalid JWT and remove it
|
|
2076
2113
|
this[accessToken] = undefined;
|
|
2077
2114
|
throw new Error('Unauthenticated');
|
|
2078
2115
|
});
|
|
2079
2116
|
}
|
|
2080
|
-
const refreshToken = this.sessionStorage.getItem(
|
|
2117
|
+
const refreshToken = this.sessionStorage.getItem(storeKeyRefreshToken);
|
|
2081
2118
|
if (refreshToken) {
|
|
2082
|
-
this.log.
|
|
2119
|
+
this.log.debug('refresh token found', { refreshToken });
|
|
2083
2120
|
/**
|
|
2084
|
-
*
|
|
2085
|
-
*
|
|
2121
|
+
* Only exchange refresh token if this is the final state (see startFinalState function for more details)
|
|
2122
|
+
*
|
|
2123
|
+
* If this is a duplicated-session, an error will be thrown and authentication will be (probably)
|
|
2124
|
+
* restarted by the caller.
|
|
2086
2125
|
*/
|
|
2087
|
-
|
|
2126
|
+
if (this.inFinalState()) {
|
|
2127
|
+
this.log.info('refreshing token', refreshToken);
|
|
2128
|
+
/**
|
|
2129
|
+
* Refresh token found in the storage,
|
|
2130
|
+
* let's use it to get new access token
|
|
2131
|
+
*/
|
|
2132
|
+
return this.exchangeRefresh(refreshToken);
|
|
2133
|
+
}
|
|
2088
2134
|
}
|
|
2089
2135
|
throw new Error('Unauthenticated');
|
|
2090
2136
|
});
|
|
2091
2137
|
}
|
|
2092
2138
|
logout() {
|
|
2093
|
-
this[accessToken] = undefined;
|
|
2094
|
-
this[user] = undefined;
|
|
2095
2139
|
this.pruneStore();
|
|
2096
2140
|
this.location.assign(Make({
|
|
2097
2141
|
url: `${this.cortezaAuthURL}/logout`,
|
|
@@ -2106,8 +2150,9 @@ class Auth {
|
|
|
2106
2150
|
*/
|
|
2107
2151
|
startAuthenticationFlow() {
|
|
2108
2152
|
this.log.debug('starting new authentication flow');
|
|
2153
|
+
this.incFlowCounter();
|
|
2109
2154
|
const state = Math.random().toString(36).substring(2);
|
|
2110
|
-
this.sessionStorage.setItem(`auth.state.${state}.location`, this.location.toString());
|
|
2155
|
+
this.sessionStorage.setItem(`auth.state.${state}.location`, this.getRedirect(this.location.toString()));
|
|
2111
2156
|
this.location.assign(Make({
|
|
2112
2157
|
url: `${this.cortezaAuthURL}` + oauth2FlowURL,
|
|
2113
2158
|
query: {
|
|
@@ -2118,6 +2163,38 @@ class Auth {
|
|
|
2118
2163
|
},
|
|
2119
2164
|
}));
|
|
2120
2165
|
}
|
|
2166
|
+
getRedirect(url) {
|
|
2167
|
+
const u = new URL(url);
|
|
2168
|
+
// In case someone started the flow on a callback route, default to the root
|
|
2169
|
+
// of the webapp.
|
|
2170
|
+
if (this.isCallback(u.pathname)) {
|
|
2171
|
+
u.pathname = '';
|
|
2172
|
+
u.search = '';
|
|
2173
|
+
u.hash = '';
|
|
2174
|
+
}
|
|
2175
|
+
return u.toString();
|
|
2176
|
+
}
|
|
2177
|
+
isCallback(url) {
|
|
2178
|
+
return /\/auth\/callback$/.test(url);
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* protects against too many tries when we try to auto-fix the "state does not match" error
|
|
2182
|
+
* by restarting the aut flow.
|
|
2183
|
+
*/
|
|
2184
|
+
incFlowCounter() {
|
|
2185
|
+
const aux = this.sessionStorage.getItem(storeKeyFlowStarted);
|
|
2186
|
+
if (aux === null) {
|
|
2187
|
+
this.sessionStorage.setItem(storeKeyFlowStarted, '1');
|
|
2188
|
+
return;
|
|
2189
|
+
}
|
|
2190
|
+
const count = parseInt(this.sessionStorage.getItem(storeKeyFlowStarted));
|
|
2191
|
+
if (count >= maxStartAttempts) {
|
|
2192
|
+
// Too many start attempts
|
|
2193
|
+
this.sessionStorage.removeItem(storeKeyFlowStarted);
|
|
2194
|
+
throw new Error('could not start authentication flow, too many attempts');
|
|
2195
|
+
}
|
|
2196
|
+
this.sessionStorage.setItem(storeKeyFlowStarted, (count + 1).toString());
|
|
2197
|
+
}
|
|
2121
2198
|
/**
|
|
2122
2199
|
* Exchanges authorization code for access and refresh tokens
|
|
2123
2200
|
*/
|
|
@@ -2141,6 +2218,10 @@ class Auth {
|
|
|
2141
2218
|
*/
|
|
2142
2219
|
exchangeRefresh(refreshToken) {
|
|
2143
2220
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2221
|
+
/**
|
|
2222
|
+
* Finalize
|
|
2223
|
+
*/
|
|
2224
|
+
this.completeFinalState();
|
|
2144
2225
|
return this.oauth2token({
|
|
2145
2226
|
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
2146
2227
|
refresh_token: refreshToken || '',
|
|
@@ -2184,7 +2265,7 @@ class Auth {
|
|
|
2184
2265
|
this.startAuthenticationFlow();
|
|
2185
2266
|
});
|
|
2186
2267
|
}), 1000 * timeout);
|
|
2187
|
-
this.sessionStorage.setItem(
|
|
2268
|
+
this.sessionStorage.setItem(storeKeyRefreshToken, oa2tkn.refresh_token);
|
|
2188
2269
|
const u = new system.User({
|
|
2189
2270
|
userID: oa2tkn.sub,
|
|
2190
2271
|
name: oa2tkn.name,
|