Skip to content

Commit

Permalink
fixes after actual-server reviews and fixes from merge
Browse files Browse the repository at this point in the history
  • Loading branch information
lelemm committed Nov 8, 2024
1 parent d4b0e49 commit 30afb0e
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 44 deletions.
2 changes: 1 addition & 1 deletion packages/desktop-client/src/auth/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const AuthProvider = ({ children }: AuthProviderProps) => {

return (
(userData?.offline ?? false) ||
(userData?.permissions?.includes(permission?.toUpperCase()) ?? false)
userData?.permission?.toUpperCase() === permission?.toUpperCase()
);
};

Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-client/src/auth/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export enum Permissions {
ADMINISTRATOR = 'ADMINISTRATOR',
ADMINISTRATOR = 'ADMIN',
}
27 changes: 22 additions & 5 deletions packages/desktop-client/src/components/ServerContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, {
} from 'react';

import { send } from 'loot-core/src/platform/client/fetch';
import { type Handlers } from 'loot-core/types/handlers';

type LoginMethods = {
method: string;
Expand All @@ -25,6 +26,8 @@ type ServerContextValue = {
opts?: { validate?: boolean },
) => Promise<{ error?: string }>;
refreshLoginMethods: () => Promise<void>;
setMultiuserEnabled: (enabled: boolean) => void;
setLoginMethods: (methods: LoginMethods[]) => void;
};

const ServerContext = createContext<ServerContextValue>({
Expand All @@ -35,6 +38,8 @@ const ServerContext = createContext<ServerContextValue>({
setURL: () => Promise.reject(new Error('ServerContext not initialized')),
refreshLoginMethods: () =>
Promise.reject(new Error('ServerContext not initialized')),
setMultiuserEnabled: () => {},
setLoginMethods: () => {},
});

export const useServerURL = () => useContext(ServerContext).url;
Expand Down Expand Up @@ -69,6 +74,12 @@ async function getServerVersion() {
export const useRefreshLoginMethods = () =>
useContext(ServerContext).refreshLoginMethods;

export const useSetMultiuserEnabled = () =>
useContext(ServerContext).setMultiuserEnabled;

export const useSetLoginMethods = () =>
useContext(ServerContext).setLoginMethods;

export function ServerProvider({ children }: { children: ReactNode }) {
const [serverURL, setServerURL] = useState('');
const [version, setVersion] = useState('');
Expand All @@ -93,13 +104,17 @@ export function ServerProvider({ children }: { children: ReactNode }) {
}, [serverURL]);

useEffect(() => {
refreshLoginMethods();
if (serverURL) {
send('multiuser-get').then((data: boolean) => {
setMultiuserEnabled(data);
});
send('subscribe-needs-bootstrap').then(
(data: Awaited<ReturnType<Handlers['subscribe-needs-bootstrap']>>) => {
if ('hasServer' in data && data.hasServer) {
setAvailableLoginMethods(data.loginMethods);
setMultiuserEnabled(data.multiuser);
}
},
);
}
}, [serverURL, refreshLoginMethods]);
}, [serverURL]);

const setURL = useCallback(
async (url: string, opts: { validate?: boolean } = {}) => {
Expand All @@ -122,6 +137,8 @@ export function ServerProvider({ children }: { children: ReactNode }) {
setURL,
version: version ? `v${version}` : 'N/A',
refreshLoginMethods,
setMultiuserEnabled,
setLoginMethods: setAvailableLoginMethods,
}}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import React, {
} from 'react';
import { useDispatch } from 'react-redux';

import { css } from 'glamor';
import { css } from '@emotion/css';

import { pushModal } from 'loot-core/src/client/actions/modals';
import { pushModal } from 'loot-core/client/actions';
import { send } from 'loot-core/src/platform/client/fetch';
import * as undo from 'loot-core/src/platform/client/undo';
import { type Handlers } from 'loot-core/types/handlers';
import { type UserAvailable } from 'loot-core/types/models';
import { type UserAccessEntity } from 'loot-core/types/models/userAccess';

Expand Down Expand Up @@ -100,8 +101,16 @@ function UserAccessContent({
}, [cloudFileId, setLoading]);

const loadOwner = useCallback(async () => {
const owner = (await send('file-owner-get', cloudFileId as string)) ?? {};
return owner;
debugger;
const file: Awaited<ReturnType<Handlers['get-user-file-info']>> =
(await send('get-user-file-info', cloudFileId as string)) ?? {};
const owner = file?.usersWithAccess.filter(user => user.owner);

if (owner.length > 0) {
return owner[0];
}

return null;
}, [cloudFileId]);

useEffect(() => {
Expand Down Expand Up @@ -325,7 +334,7 @@ const iconStyle = css({
});

const LockToggle = props => (
<div {...wrapperStyle}>
<div className={wrapperStyle}>
<div className={`${iconStyle} default-icon`}>
<SvgLockClosed {...props} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function OpenIdLogin({ setError }) {

async function onSetOpenId(config: OpenIdConfig) {
setError(null);
const { error } = await send('subscribe-bootstrap', { openid: config });
const { error } = await send('subscribe-bootstrap', { openId: config });

if (error) {
setError(error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';

import { send } from 'loot-core/src/platform/client/fetch';
import { type Handlers } from 'loot-core/types/handlers';

import { useNavigate } from '../../../hooks/useNavigate';
import { theme } from '../../../style';
import { useSetServerURL } from '../../ServerContext';
import {
useSetLoginMethods,
useSetMultiuserEnabled,
useSetServerURL,
} from '../../ServerContext';

// There are two URLs that dance with each other: `/login` and
// `/bootstrap`. Both of these URLs check the state of the the server
Expand All @@ -22,6 +27,8 @@ export function useBootstrapped(redirect = true) {
const navigate = useNavigate();
const location = useLocation();
const setServerURL = useSetServerURL();
const setMultiuserEnabled = useSetMultiuserEnabled();
const setLoginMethods = useSetLoginMethods();

useEffect(() => {
async function run() {
Expand All @@ -40,7 +47,9 @@ export function useBootstrapped(redirect = true) {
if (url == null && !bootstrapped) {
// A server hasn't been specified yet
const serverURL = window.location.origin;
const result = await send('subscribe-needs-bootstrap', {
const result: Awaited<
ReturnType<Handlers['subscribe-needs-bootstrap']>
> = await send('subscribe-needs-bootstrap', {
url: serverURL,
});

Expand All @@ -52,17 +61,28 @@ export function useBootstrapped(redirect = true) {

await setServerURL(serverURL, { validate: false });

setMultiuserEnabled(result.multiuser);
setLoginMethods(result.loginMethods);

if (result.bootstrapped) {
ensure(`/login`);
} else {
ensure('/bootstrap');
}
} else {
const result = await send('subscribe-needs-bootstrap');
const result: Awaited<
ReturnType<Handlers['subscribe-needs-bootstrap']>
> = await send('subscribe-needs-bootstrap');

if ('error' in result) {
navigate('/error', { state: { error: result.error } });
} else if (result.bootstrapped) {
ensure(`/login`);

if ('hasServer' in result && result.hasServer) {
setMultiuserEnabled(result.multiuser);
setLoginMethods(result.loginMethods);
}
} else {
ensure('/bootstrap');
}
Expand Down
4 changes: 1 addition & 3 deletions packages/desktop-client/src/components/modals/EditUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,7 @@ function EditUser({ defaultUser, onSave: originalOnSave }: EditUserProps) {
defaultUser.displayName ?? '',
);
const [enabled, setEnabled] = useState<boolean>(defaultUser.enabled);
const [role, setRole] = useState<string>(
defaultUser.role ?? '213733c1-5645-46ad-8784-a7b20b400f93',
);
const [role, setRole] = useState<string>(defaultUser.role ?? 'BASIC');
const [error, setError] = useState<string>('');

async function onSave() {
Expand Down
13 changes: 1 addition & 12 deletions packages/loot-core/src/server/admin/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ app.method('access-delete-all', async function ({ fileId, ids }) {
const userToken = await asyncStorage.getItem('user-token');
if (userToken) {
try {
debugger;
const res = await del(
getServer().BASE_SERVER + `/admin/access?fileId=${fileId}`,
{
Expand Down Expand Up @@ -231,18 +230,8 @@ app.method('file-owner-get', async function (fileId) {
return null;
});

app.method('multiuser-get', async function () {
const res = await get(getServer().BASE_SERVER + '/admin/multiuser/');

if (res) {
return (JSON.parse(res) as boolean) || false;
}

return null;
});

app.method('owner-created', async function () {
const res = await get(getServer().BASE_SERVER + '/admin/ownerCreated/');
const res = await get(getServer().BASE_SERVER + '/admin/owner-created/');

if (res) {
return JSON.parse(res) as boolean;
Expand Down
2 changes: 0 additions & 2 deletions packages/loot-core/src/server/admin/types/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,5 @@ export interface AdminHandlers {

'file-owner-get': (fileId: string) => Promise<UserEntity | null>;

'multiuser-get': () => Promise<boolean | null>;

'owner-created': () => Promise<boolean>;
}
32 changes: 32 additions & 0 deletions packages/loot-core/src/server/cloud-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,38 @@ export async function listRemoteFiles(): Promise<RemoteFile[] | null> {
}));
}

export async function getRemoteFile(
fileId: string,
): Promise<RemoteFile | null> {
const userToken = await asyncStorage.getItem('user-token');
if (!userToken) {
return null;
}

let res;
try {
res = await fetchJSON(getServer().SYNC_SERVER + '/get-user-file-info', {
headers: {
'X-ACTUAL-TOKEN': userToken,
'X-ACTUAL-FILE-ID': fileId,
},
});
} catch (e) {
console.log('Unexpected error fetching file from server', e);
return null;
}

if (res.status === 'error') {
console.log('Error fetching file from server', res);
return null;
}

return {
...res.data,
hasKey: encryption.hasKey(res.data.encryptKeyId),
};
}

export async function download(fileId) {
const userToken = await asyncStorage.getItem('user-token');
const syncServer = getServer().SYNC_SERVER;
Expand Down
13 changes: 10 additions & 3 deletions packages/loot-core/src/server/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1541,7 +1541,10 @@ handlers['subscribe-needs-bootstrap'] = async function ({

return {
bootstrapped: res.data.bootstrapped,
loginMethod: res.data.loginMethod || 'password',
loginMethods: res.data.loginMethods || [
{ method: 'password', active: true, displayName: 'Password' },
],
multiuser: res.data.multiuser || false,
hasServer: true,
};
};
Expand Down Expand Up @@ -1597,7 +1600,7 @@ handlers['subscribe-get-user'] = async function () {
reason,
data: {
userName = null,
permissions = [],
permission = '',
userId = null,
displayName = null,
loginMethod = null,
Expand All @@ -1617,7 +1620,7 @@ handlers['subscribe-get-user'] = async function () {
return {
offline: false,
userName,
permissions,
permission,
userId,
displayName,
loginMethod,
Expand Down Expand Up @@ -1783,6 +1786,10 @@ handlers['get-remote-files'] = async function () {
return cloudStorage.listRemoteFiles();
};

handlers['get-user-file-info'] = async function (fileId: string) {
return cloudStorage.getRemoteFile(fileId);
};

handlers['reset-budget-cache'] = mutator(async function () {
// Recomputing everything will update the cache
await sheet.loadUserBudgets(db);
Expand Down
4 changes: 2 additions & 2 deletions packages/loot-core/src/types/models/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ export interface UserAvailable {
}

export const PossibleRoles = {
'213733c1-5645-46ad-8784-a7b20b400f93': 'Admin',
'e87fa1f1-ac8c-4913-b1b5-1096bdb1eacc': 'Basic',
ADMIN: 'Admin',
BASIC: 'Basic',
};
26 changes: 20 additions & 6 deletions packages/loot-core/src/types/server-handlers.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,22 @@ export interface ServerHandlers {

'get-did-bootstrap': () => Promise<boolean>;

'subscribe-needs-bootstrap': (args: {
url;
}) => Promise<
{ error: string } | { bootstrapped: unknown; hasServer: boolean }
'subscribe-needs-bootstrap': (args: { url }) => Promise<
| { error: string }
| {
bootstrapped: boolean;
hasServer: false;
}
| {
bootstrapped: boolean;
hasServer: true;
loginMethods: {
method: string;
displayName: string;
active: boolean;
}[];
multiuser: boolean;
}
>;

'subscribe-get-login-methods': () => Promise<{
Expand All @@ -280,15 +292,15 @@ export interface ServerHandlers {

'subscribe-bootstrap': (arg: {
password?: string;
openid?: OpenIdConfig;
openId?: OpenIdConfig;
}) => Promise<{ error?: string }>;

'subscribe-get-user': () => Promise<{
offline: boolean;
userName?: string;
userId?: string;
displayName?: string;
permissions?: string[];
permission?: string;
loginMethod?: string;
tokenExpired?: boolean;
} | null>;
Expand Down Expand Up @@ -331,6 +343,8 @@ export interface ServerHandlers {

'get-remote-files': () => Promise<RemoteFile[]>;

'get-user-file-info': (fileId: string) => Promise<RemoteFile | null>;

'reset-budget-cache': () => Promise<unknown>;

'upload-budget': (arg: { id }) => Promise<{ error?: string }>;
Expand Down

0 comments on commit 30afb0e

Please sign in to comment.