diff --git a/templates/create-daml-app/daml/Setup.daml b/templates/create-daml-app/daml/Setup.daml index 3564f5c7563c..4b58289c539e 100644 --- a/templates/create-daml-app/daml/Setup.daml +++ b/templates/create-daml-app/daml/Setup.daml @@ -5,8 +5,6 @@ import DA.Optional (fromSomeNote) import qualified DA.Text as T import Daml.Script -import User (Alias(..)) - -- | A test user for the create-daml-app network. data TestUser = TestUser with alias : Text @@ -24,7 +22,6 @@ createTestUser : TestUser -> Script Party createTestUser TestUser{alias, public} = do u <- getOrCreateUser alias (Some public) let p = getPrimaryParty u - submit p $ createCmd $ Alias p alias public pure p -- | Create the public party. @@ -44,7 +41,7 @@ getOrCreateUser alias publicM = do UserNotFound _ -> do p <- allocateParty alias let u = User userId (Some p) - createUser u $ [CanActAs p] ++ [CanReadAs public | Some public <- [publicM]] + createUser u $ CanActAs p :: [CanReadAs public | Some public <- [publicM]] pure u -- | Convert a text to a valid user id. diff --git a/templates/create-daml-app/daml/User.daml b/templates/create-daml-app/daml/User.daml index bca2311e7298..d6cf779011b1 100644 --- a/templates/create-daml-app/daml/User.daml +++ b/templates/create-daml-app/daml/User.daml @@ -6,7 +6,6 @@ module User where -- MAIN_TEMPLATE_BEGIN template User with username: Party - public: Party following: [Party] where signatory username diff --git a/templates/create-daml-app/ui/src/Credentials.ts b/templates/create-daml-app/ui/src/Credentials.ts index 64c0f8140bf0..08b5c7c7070a 100644 --- a/templates/create-daml-app/ui/src/Credentials.ts +++ b/templates/create-daml-app/ui/src/Credentials.ts @@ -6,6 +6,7 @@ import { User } from "@daml/ledger"; export type Credentials = { party: string; + publicParty: string; token: string; user: User; } diff --git a/templates/create-daml-app/ui/src/components/LoginScreen.tsx.template b/templates/create-daml-app/ui/src/components/LoginScreen.tsx.template index 23f8e8b98cef..c12709c870d3 100644 --- a/templates/create-daml-app/ui/src/components/LoginScreen.tsx.template +++ b/templates/create-daml-app/ui/src/components/LoginScreen.tsx.template @@ -14,6 +14,9 @@ type Props = { onLogin: (credentials: Credentials) => void; } +const toAlias = (userId: string): string => + userId.charAt(0).toUpperCase() + userId.slice(1); + /** * React component for the login screen of the `App`. */ @@ -24,9 +27,13 @@ const LoginScreen: React.FC = ({onLogin}) => { const ledger = new Ledger({token: credentials.token}); let userContract = await ledger.fetchByKey(User.User, credentials.party); if (userContract === null) { - const user = {username: credentials.party, following: [], public: 'public'}; + const user = {username: credentials.party, following: []}; userContract = await ledger.create(User.User, user); } + let userAlias = await ledger.fetchByKey(User.Alias, {_1: credentials.party, _2: credentials.publicParty}); + if (userAlias === null) { + await ledger.create(User.Alias, {username: credentials.party, alias: toAlias(credentials.user.userId), public: credentials.publicParty}); + } onLogin(credentials); } catch(error) { alert(`Unknown error:\n${JSON.stringify(error)}`); @@ -72,8 +79,14 @@ const LoginScreen: React.FC = ({onLogin}) => { alert(`Failed to login as '${username}':\n${errorMsg}`); throw error; }); + const publicParty:string = await auth.userManagement.publicParty(username, ledger).catch((error) => { + const errorMsg = error instanceof Error ? error.toString() : JSON.stringify(error); + alert(`Failed to login as '${username}':\n${errorMsg}`); + throw error; + }); await login({user: {userId: username, primaryParty: primaryParty}, party: primaryParty, + publicParty: publicParty, token: auth.makeToken(username)}); } @@ -100,7 +113,8 @@ const LoginScreen: React.FC = ({onLogin}) => { { if (creds) { - login({party:creds.party, user: {userId: creds.partyName, primaryParty: creds.party}, token:creds.token}); + // TODO (MK) Fix public party in Daml hub + login({party:creds.party, publicParty: "FIXME", user: {userId: creds.partyName, primaryParty: creds.party}, token:creds.token}); } }} options={{ @@ -120,9 +134,11 @@ const LoginScreen: React.FC = ({onLogin}) => { if (isLoading === false && isAuthenticated === true) { if (user !== undefined) { const party = user["https://daml.com/ledger-api"]; + // TODO (MK) Fix public party with Auth0 const creds: Credentials = { user: {userId: user.email ?? user.name ?? party, primaryParty: party}, party: party, + publicParty: "FIXME", token: (await getAccessTokenSilently({ audience: "https://daml.com/ledger-api"}))}; login(creds); diff --git a/templates/create-daml-app/ui/src/config.ts.template b/templates/create-daml-app/ui/src/config.ts.template index b456f8aa4c24..33e512be0c07 100644 --- a/templates/create-daml-app/ui/src/config.ts.template +++ b/templates/create-daml-app/ui/src/config.ts.template @@ -3,11 +3,12 @@ import { encode } from 'jwt-simple'; import { isRunningOnHub } from '@daml/hub-react'; -import Ledger from '@daml/ledger'; +import Ledger, { CanReadAs } from '@daml/ledger'; export type UserManagement = { tokenPayload: (loginName: string, ledgerId: string) => Object, primaryParty: (loginName: string, ledger: Ledger) => Promise, + publicParty: (loginName: string, ledger: Ledger) => Promise, }; export type Insecure = { @@ -39,6 +40,9 @@ export const noUserManagement: UserManagement = { } }), primaryParty: async (loginName: string, ledger: Ledger) => loginName, + // Without user management, we force a specific party id here because + // we mainly care about this for vmbc and there we can support this. + publicParty: async (loginName: string, ledger: Ledger) => 'public', }; // Used on SDK >= 2.0.0 with the exception of VMBC @@ -56,6 +60,17 @@ export const withUserManagement: UserManagement = { throw new Error(`User '${loginName}' has no primary party`); } + }, + publicParty: async (loginName, ledger: Ledger) => { + const rights = await ledger.listUserRights(); + const readAsRights: CanReadAs[] = rights.filter((x) : x is CanReadAs => x.type === "CanReadAs"); + if (readAsRights.length === 0) { + throw new Error(`User '${loginName} has no readAs claims for a public party`); + } else if (readAsRights.length > 1) { + throw new Error(`User '${loginName} has readAs claims for more than one party`); + } else { + return readAsRights[0].party; + } } };