@vertesia/ui 0.79.1 → 0.80.0-dev-20251118

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.
@@ -32,95 +32,96 @@ export async function fetchComposableToken(getIdToken: () => Promise<string | nu
32
32
  throw new Error('No id token found');
33
33
  }
34
34
 
35
- console.log('Fetching composable token from ' + Env.endpoints.studio);
36
- Env.logger.info('Fetching composable token from' + Env.endpoints.studio, {
35
+ // Use STS endpoint - either configured or default to sts.vertesia.io
36
+ const stsEndpoint = Env.endpoints.sts;
37
+ console.log('Using STS for token generation:', stsEndpoint);
38
+ Env.logger.info('Using STS for token generation', {
37
39
  vertesia: {
38
40
  account_id: accountId,
39
41
  project_id: projectId,
42
+ sts_url: stsEndpoint,
40
43
  },
41
44
  });
42
45
 
43
- const url = new URL(Env.endpoints.studio + '/auth/token');
44
- if (accountId) url.searchParams.set('accountId', accountId);
45
- if (projectId) url.searchParams.set('projectId', projectId);
46
- if (ttl) url.searchParams.set('ttl', String(ttl));
47
-
48
- console.log(`Getting composable token for account ${accountId} and project ${projectId}`);
49
- Env.logger.info('Getting composable token', {
50
- vertesia: {
46
+ try {
47
+ // Call STS to generate a user token
48
+ const stsUrl = new URL(stsEndpoint + '/token/issue');
49
+ const requestBody = {
50
+ type: 'user',
51
51
  account_id: accountId,
52
52
  project_id: projectId,
53
- },
54
- });
55
-
56
- const res = await fetch(url, {
57
- method: 'GET',
58
- headers: {
59
- 'Content-Type': 'application/json',
60
- 'Authorization': `Bearer ${idToken}`
61
- }
62
- }).catch(err => {
63
- localStorage.removeItem(LastSelectedAccountId_KEY);
64
- localStorage.removeItem(LastSelectedProjectId_KEY);
65
- console.error('Failed to get composable token', err);
66
- Env.logger.error('Failed to get composable token', {
67
- vertesia: {
68
- account_id: accountId,
69
- project_id: projectId,
70
- error: err,
53
+ expires_at: ttl ? Math.floor(Date.now() / 1000) + ttl : undefined,
54
+ };
55
+
56
+ const stsRes = await fetch(stsUrl, {
57
+ method: 'POST',
58
+ headers: {
59
+ 'Content-Type': 'application/json',
60
+ 'Authorization': `Bearer ${idToken}` // Firebase token for authentication
71
61
  },
62
+ body: JSON.stringify(requestBody)
72
63
  });
73
- throw new Error('Failed to get composable token');
74
- });
75
64
 
76
- if (idToken && res?.status === 412) {
77
- console.log("412: auth succeeded but user doesn't exist - signup required", res?.status);
78
- Env.logger.error("412: auth succeeded but user doesn't exist - signup required", {
79
- vertesia: {
80
- account_id: accountId,
81
- project_id: projectId,
82
- status: res?.status
83
- },
84
- });
85
- const idTokenDecoded = jwtDecode(idToken) as any;
86
- if (!idTokenDecoded?.email) {
87
- Env.logger.error('No email found in id token');
88
- throw new Error('No email found in id token');
89
- }
90
- Env.logger.error('User not found', {
91
- vertesia: {
92
- account_id: accountId,
93
- project_id: projectId,
94
- email: idTokenDecoded.email
65
+ if (idToken && stsRes?.status === 412) {
66
+ console.log("412: auth succeeded but user doesn't exist - signup required", stsRes?.status);
67
+ Env.logger.error("412: auth succeeded but user doesn't exist - signup required", {
68
+ vertesia: {
69
+ account_id: accountId,
70
+ project_id: projectId,
71
+ status: stsRes?.status
72
+ },
73
+ });
74
+ const idTokenDecoded = jwtDecode(idToken) as any;
75
+ if (!idTokenDecoded?.email) {
76
+ Env.logger.error('No email found in id token');
77
+ throw new Error('No email found in id token');
95
78
  }
96
- });
97
- throw new UserNotFoundError('User not found', idTokenDecoded.email);
98
- }
79
+ Env.logger.error('User not found', {
80
+ vertesia: {
81
+ account_id: accountId,
82
+ project_id: projectId,
83
+ email: idTokenDecoded.email
84
+ }
85
+ });
86
+ throw new UserNotFoundError('User not found', idTokenDecoded.email);
87
+ }
88
+
89
+ if (!stsRes.ok) {
90
+ const errorText = await stsRes.text();
91
+ console.error('STS token generation failed:', stsRes.status, errorText);
92
+ Env.logger.error('STS token generation failed', {
93
+ vertesia: {
94
+ status: stsRes.status,
95
+ error: errorText,
96
+ account_id: accountId,
97
+ project_id: projectId,
98
+ },
99
+ });
100
+ throw new Error(`Failed to get token from STS: ${stsRes.status}`);
101
+ }
102
+
103
+ const { token } = await stsRes.json();
104
+ console.log('Successfully got token from STS');
105
+ Env.logger.info('Successfully got token from STS');
106
+ return token;
99
107
 
100
- if (!res || !res.ok) {
101
- console.error('Failed to get composable token', res);
102
- Env.logger.error('Failed to get composable token', {
108
+ } catch (error) {
109
+ if (error instanceof UserNotFoundError) {
110
+ throw error; // Re-throw UserNotFoundError
111
+ }
112
+
113
+ localStorage.removeItem(LastSelectedAccountId_KEY);
114
+ localStorage.removeItem(LastSelectedProjectId_KEY);
115
+ console.error('Failed to get composable token from STS', error);
116
+ Env.logger.error('Failed to get composable token from STS', {
103
117
  vertesia: {
104
118
  account_id: accountId,
105
119
  project_id: projectId,
106
- status: res?.status,
120
+ error: error,
107
121
  },
108
122
  });
109
123
  throw new Error('Failed to get composable token');
110
124
  }
111
-
112
- const { token } = await res.json().catch(err => {
113
- Env.logger.error('Failed to parse composable token', {
114
- vertesia: {
115
- account_id: accountId,
116
- project_id: projectId,
117
- error: err,
118
- },
119
- });
120
- console.error('Failed to parse composable token', err);
121
- });
122
-
123
- return token;
124
125
  }
125
126
 
126
127
  /**
@@ -187,4 +188,4 @@ export class UserNotFoundError extends Error {
187
188
  this.name = 'UserNotFoundError';
188
189
  this.email = email;
189
190
  }
190
- }
191
+ }
@@ -1,5 +1,5 @@
1
1
  import { ProjectRef, RequireAtLeastOne } from "@vertesia/common";
2
- import { SelectBox, useFetch } from "@vertesia/ui/core";
2
+ import { VSelectBox, useFetch } from "@vertesia/ui/core";
3
3
  import { LastSelectedAccountId_KEY, LastSelectedProjectId_KEY, useUserSession } from "@vertesia/ui/session";
4
4
  import { useState } from "react";
5
5
 
@@ -47,7 +47,7 @@ function SelectProject({ initialValue, projects, onChange, placeholder = "Select
47
47
  }
48
48
  let actualValue = !value && initialValue ? projects.find(p => p.id === initialValue) : value;
49
49
  return (
50
- <SelectBox
50
+ <VSelectBox
51
51
  by="id"
52
52
  value={actualValue}
53
53
  options={projects}
@@ -97,7 +97,7 @@ export function ScalarField({ object, editor, inline = false }: ScalarFieldProps
97
97
  return (
98
98
  <FormItem label={object.title} required={object.schema.isRequired} description={object.schema.description}
99
99
  className={clsx('flex', inline ? 'flex-row items-center' : 'flex-col')}>
100
- {!object.isListItem && <Component object={object} type={inputType} onChange={handleOnChange} />}
100
+ {!object.isListItem && <Component object={object} type={inputType} onChange={handleOnChange} disabled={disabled} />}
101
101
  </FormItem>
102
102
  )
103
103
  }
@@ -10,6 +10,10 @@ function getInputType(_name: string, schema: PropertySchema) {
10
10
  if (schema.editor) {
11
11
  return schema.editor;
12
12
  }
13
+ // Check format as fallback (e.g., "document", "media", "date", etc.)
14
+ if (schema.schema.format) {
15
+ return schema.schema.format;
16
+ }
13
17
  switch (schema.type) {
14
18
  case 'number':
15
19
  case 'integer':