1import gql from 'graphql-tag'; 2 3import * as Log from '../../log'; 4import * as Analytics from '../../utils/analytics/rudderstackClient'; 5import { graphqlClient } from '../graphql/client'; 6import { CurrentUserQuery } from '../graphql/generated'; 7import { UserQuery } from '../graphql/queries/UserQuery'; 8import { fetchAsync } from '../rest/client'; 9import UserSettings from './UserSettings'; 10 11export type Actor = NonNullable<CurrentUserQuery['meActor']>; 12 13let currentUser: Actor | undefined; 14 15export const ANONYMOUS_USERNAME = 'anonymous'; 16 17/** 18 * Resolve the name of the actor, either normal user or robot user. 19 * This should be used whenever the "current user" needs to be displayed. 20 * The display name CANNOT be used as project owner. 21 */ 22export function getActorDisplayName(user?: Actor): string { 23 switch (user?.__typename) { 24 case 'User': 25 return user.username; 26 case 'Robot': 27 return user.firstName ? `${user.firstName} (robot)` : 'robot'; 28 default: 29 return ANONYMOUS_USERNAME; 30 } 31} 32 33export async function getUserAsync(): Promise<Actor | undefined> { 34 if (!currentUser && (UserSettings.getAccessToken() || UserSettings.getSession()?.sessionSecret)) { 35 const user = await UserQuery.currentUserAsync(); 36 currentUser = user ?? undefined; 37 if (user) { 38 await Analytics.setUserDataAsync(user.id, { 39 username: getActorDisplayName(user), 40 user_id: user.id, 41 user_type: user.__typename, 42 }); 43 } 44 } 45 return currentUser; 46} 47 48export async function loginAsync(json: { 49 username: string; 50 password: string; 51 otp?: string; 52}): Promise<void> { 53 const res = await fetchAsync('auth/loginAsync', { 54 method: 'POST', 55 body: JSON.stringify(json), 56 }); 57 const { 58 data: { sessionSecret }, 59 } = await res.json(); 60 const result = await graphqlClient 61 .query( 62 gql` 63 query UserQuery { 64 viewer { 65 id 66 username 67 } 68 } 69 `, 70 {}, 71 { 72 fetchOptions: { 73 headers: { 74 'expo-session': sessionSecret, 75 }, 76 }, 77 additionalTypenames: [] /* UserQuery has immutable fields */, 78 } 79 ) 80 .toPromise(); 81 const { 82 data: { viewer }, 83 } = result; 84 await UserSettings.setSessionAsync({ 85 sessionSecret, 86 userId: viewer.id, 87 username: viewer.username, 88 currentConnection: 'Username-Password-Authentication', 89 }); 90} 91 92export async function logoutAsync(): Promise<void> { 93 currentUser = undefined; 94 await UserSettings.setSessionAsync(undefined); 95 Log.log('Logged out'); 96} 97