Skip to content

Commit

Permalink
Adds authentication guard + redirects to login in local mode
Browse files Browse the repository at this point in the history
This is generally a no-op, but it is nice to have for the local
authenticated version. A bit of a hack, but this is really just a quick
way to get something up and running. In the medium term we will be
changing the way we do auth to be more unified.
  • Loading branch information
elijahbenizzy committed Jul 3, 2024
1 parent a2b1774 commit f2a5d2b
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 36 deletions.
1 change: 0 additions & 1 deletion ui/backend/server/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ def run(
env = {**_load_env(config_file), **env}
with set_env_variables(env):
settings_file_param = f"--settings={settings_file.value}"
# execute_from_command_line(["manage.py", "collectstatic", settings_file_param])
if not no_migration:
execute_from_command_line(["manage.py", "migrate", settings_file_param])
execute_from_command_line(
Expand Down
58 changes: 33 additions & 25 deletions ui/frontend/src/auth/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,51 @@ export const UserContext = createContext<UserContextType | undefined>(
undefined
);


export const LocalLoginProvider = (props: { children: React.ReactNode }) => {
const [localUsername, setLocalUsername] = useState<string>("");
const [localAPIKey, setLocalAPIKey] = useState<string | undefined>("");
const [keyInputExpanded, setKeyInputExpanded] = useState(false);

const [username, setUsername] = useLocalStorage(
"hamilton-username",
undefined
);
const [apiKey, setApiKey] = useLocalStorage("hamilton-api-key", undefined);

if (username) {
const [authed, setAuthed] = useLocalStorage("authed", "false");
if (authed === "true") {
return (
<UserContext.Provider
value={{ username, setUsername, userAPIKey: apiKey }}
value={{ username: username || "", setUsername, userAPIKey: apiKey }}
>
{props.children}
{props.children}
</UserContext.Provider>
);
}

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setLocalUsername(event.target.value);
};

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
setUsername(localUsername); // Store username
if (authed != "true") {
const results = fetch("/api/v1/phone_home", {
method: "GET",
headers: {
"x-api-key": localAPIKey || "",
"x-api-user": localUsername || "",
},
});
results.then((response) => {
if (response.status !== 200) {
setUsername(undefined);
setApiKey(undefined);
setAuthed("false");
}
else {
setAuthed("true");
setUsername(localUsername); // Store username
setApiKey(localAPIKey); // Store API key
}
});
}
};

const KeyInputExpandIcon = keyInputExpanded ? HiChevronUp : HiChevronDown;
Expand All @@ -58,8 +76,8 @@ export const LocalLoginProvider = (props: { children: React.ReactNode }) => {
type="text"
autoComplete="username"
name="username"
value={username}
onChange={handleChange}
value={localUsername}
onChange={(event) => setLocalUsername(event.target.value)}
placeholder="Username"
required
className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-dwdarkblue focus:border-dwdarkblue focus:z-10 sm:text-sm"
Expand All @@ -70,25 +88,14 @@ export const LocalLoginProvider = (props: { children: React.ReactNode }) => {
type="password"
autoComplete="api-key"
name="api-key"
value={apiKey || ""}
value={localAPIKey}
onChange={(event) => {
setApiKey(event.target.value);
setLocalAPIKey(event.target.value);
}}
placeholder="API Key (power-user-mode)"
required
placeholder="API Key (leave blank for local mode)"
className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-dwdarkblue focus:border-dwdarkblue focus:z-10 sm:text-sm"
/>
)}
{/* <input
type="text"
autoComplete="username"
name="username"
value={username}
onChange={handleChange}
placeholder="Username"
required
className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-dwdarkblue focus:border-dwdarkblue focus:z-10 sm:text-sm"
/> */}
<button
type="submit"
className={`group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-dwdarkblue focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-dwdarkblue`}
Expand All @@ -112,6 +119,7 @@ export const LocalLoginProvider = (props: { children: React.ReactNode }) => {
export const localLogout = (redirectOnLogin: boolean) => {
localStorage.removeItem("hamilton-username");
localStorage.removeItem("hamilton-api-key");
localStorage.removeItem("authed");
if (redirectOnLogin) {
window.location.reload();
}
Expand Down
20 changes: 10 additions & 10 deletions ui/frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,22 @@ const TelemetryProvider =

root.render(
// <React.StrictMode>
<AuthProvider
authUrl={process.env.REACT_APP_AUTH_URL as string}
displayWhileLoading={<Loading />}
displayIfLoggedOut={<RedirectToLogin />}
>
<Provider store={store}>
<PersistGate loading={<Loading />} persistor={persistor}>
<Provider store={store}>
<PersistGate loading={<Loading />} persistor={persistor}>
<AuthProvider
authUrl={process.env.REACT_APP_AUTH_URL as string}
displayWhileLoading={<Loading />}
displayIfLoggedOut={<RedirectToLogin />}
>
<TelemetryProvider
apiKey={process.env.REACT_APP_PUBLIC_POSTHOG_KEY}
options={posthogOptions}
>
<App />
</TelemetryProvider>
</PersistGate>
</Provider>
</AuthProvider>
</AuthProvider>
</PersistGate>
</Provider>
// </React.StrictMode>
);

Expand Down
1 change: 1 addition & 0 deletions ui/frontend/src/state/api/emptyApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const baseQuery = fetchBaseQuery({
} else if (process.env.REACT_APP_AUTH_MODE === "local") {
headers.set("x-api-user", getStateTyped().auth.localUserName || "");
headers.set("x-api-key", getStateTyped().auth.localAPIKey || "");
console.log(headers)
}
return headers;
},
Expand Down
3 changes: 3 additions & 0 deletions ui/frontend/src/state/api/friendlyApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
useTrackingserverAuthApiCreateApiKeyMutation,
ApiKeyOut,
DagTemplateOutWithData,
useTrackingserverAuthApiPhoneHomeQuery,
} from "./backendApiRaw";

/**
Expand Down Expand Up @@ -235,3 +236,5 @@ export function getNodeRunAttributes<T>(
})
.filter((attr) => attr.schema_version === version && attr.type === type);
}

export const usePhoneHome = useTrackingserverAuthApiPhoneHomeQuery;

0 comments on commit f2a5d2b

Please sign in to comment.