Skip to content

Commit 4051388

Browse files
authored
add require auth and require eula for orca (#20)
1 parent a11cdd2 commit 4051388

24 files changed

+530
-34
lines changed

database/tables.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ SET role webconexsadmin;
55
CREATE TABLE person (
66
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
77
identifier TEXT NOT NULL,
8-
admin BOOLEAN NOT NULL DEFAULT FALSE,
8+
accepted_orca_eula BOOLEAN NOT NULL DEFAULT FALSE,
99
UNIQUE (identifier)
1010
);
1111

web-conexs-api/src/web_conexs_api/auth.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
)
99
from fastapi.security.http import HTTPAuthorizationCredentials, HTTPBearer
1010

11-
get_bearer_token = HTTPBearer(auto_error=True)
11+
# False so we dont get a 403 when it should be a 401
12+
get_bearer_token = HTTPBearer(auto_error=False)
1213

1314
oidc_user_info_endpoint = os.environ.get("OIDC_USER_INFO_ENDPOINT")
1415
oidc_id_key = os.environ.get("OIDC_ID_KEY", "id")

web-conexs-api/src/web_conexs_api/crud.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
build_fdmnes_inputfile,
1313
build_orca_input_file,
1414
build_qe_inputfile,
15+
fdmnes_molecule_to_crystal,
1516
)
1617
from .models.models import (
1718
CrystalStructure,
@@ -176,6 +177,11 @@ def submit_orca_simulation(
176177
) -> OrcaSimulation:
177178
person = get_or_create_person(session, user_id)
178179

180+
if not person.accepted_orca_eula:
181+
raise HTTPException(
182+
status_code=403, detail="User has not accepted the Orca EULA"
183+
)
184+
179185
smodel = {
180186
"person_id": person.id,
181187
"simulation_type_id": 1,
@@ -234,19 +240,28 @@ def get_fdmnes_simulation(session, id, user_id) -> FdmnesSimulation:
234240
def get_orca_jobfile(session, id, user_id):
235241
orca_simulation = get_orca_simulation(session, id, user_id)
236242
structure = get_molecular_structure(
237-
session, orca_simulation.crystal_structure_id, user_id
243+
session, orca_simulation.molecular_structure_id, user_id
238244
)
239245

240246
return build_orca_input_file(orca_simulation, structure)
241247

242248

243249
def get_fdmnes_jobfile(session, id, user_id):
244250
fdmnes_simulation = get_fdmnes_simulation(session, id, user_id)
245-
structure = get_crystal_structure(
246-
session, fdmnes_simulation.crystal_structure_id, user_id
247-
)
248251

249-
return build_fdmnes_inputfile(fdmnes_simulation, structure)
252+
if fdmnes_simulation.crystal_structure_id is not None:
253+
structure = get_crystal_structure(
254+
session, fdmnes_simulation.crystal_structure_id, user_id
255+
)
256+
crystalIsMolecule = False
257+
else:
258+
molecule = get_molecular_structure(
259+
session, fdmnes_simulation.molecular_structure_id, user_id
260+
)
261+
structure = fdmnes_molecule_to_crystal(molecule)
262+
crystalIsMolecule = True
263+
264+
return build_fdmnes_inputfile(fdmnes_simulation, structure, crystalIsMolecule)
250265

251266

252267
def get_fdmnes_output(session, id, user_id):
@@ -341,6 +356,18 @@ def get_orca_xas(session, id, user_id):
341356
return output
342357

343358

359+
def accept_orca_eula(session, user_id):
360+
person = get_user(session, user_id)
361+
362+
person.accepted_orca_eula = True
363+
364+
session.add(person)
365+
session.commit()
366+
session.refresh(person)
367+
368+
return person
369+
370+
344371
def get_user(session, user_id):
345372
statement = select(Person).where(Person.identifier == user_id)
346373
person = session.exec(statement).first()

web-conexs-api/src/web_conexs_api/models/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77

88
class PersonInput(SQLModel):
99
identifier: str = Field(index=True, unique=True)
10+
accepted_orca_eula: bool = False
1011

1112

1213
class Person(PersonInput, table=True):
1314
__tablename__: str = "person"
1415
id: int | None = Field(primary_key=True, default=None)
15-
admin: bool = False
1616

1717

1818
class SimulationType(SQLModel, table=True):

web-conexs-api/src/web_conexs_api/routers/qe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def get_qe_jobfile_endpoint(
3535
session: Session = Depends(get_session),
3636
user_id: str = Depends(get_current_user),
3737
) -> str:
38-
return PlainTextResponse(get_qe_jobfile(session, id, user_id))
38+
return PlainTextResponse(get_qe_jobfile(session, id, user_id)[0])
3939

4040

4141
@router.get("/api/qe/{id}/output")

web-conexs-api/src/web_conexs_api/routers/user.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from sqlmodel import Session
33

44
from ..auth import get_current_user
5-
from ..crud import get_user
5+
from ..crud import accept_orca_eula, get_user
66
from ..database import get_session
77

88
router = APIRouter()
@@ -13,3 +13,10 @@ async def check(
1313
session: Session = Depends(get_session), user_id: str = Depends(get_current_user)
1414
):
1515
return get_user(session, user_id)
16+
17+
18+
@router.patch("/api/user")
19+
async def accept_orca_eula_patch(
20+
session: Session = Depends(get_session), user_id: str = Depends(get_current_user)
21+
):
22+
return accept_orca_eula(session, user_id)

web-conexs-api/tests/test_simulation_route.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ def get_session_override():
3131

3232
response = client.get("/api/simulations/")
3333

34-
print(response)
35-
36-
assert response.status_code == 403
34+
assert response.status_code == 401
3735

3836
headers = headers
3937
response = client.get("/api/simulations/", headers=headers)

web-conexs-client/src/App.tsx

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {
1818
Footer,
1919
} from "@diamondlightsource/sci-react-ui";
2020
import QeSubmitPage from "./components/qe/QESubmitPage";
21+
import OrcaEulaPage from "./components/orca/OrcaEulaPage";
22+
import RequireAuth from "./components/RequireAuth";
2123

2224
const queryClient = new QueryClient();
2325

@@ -31,23 +33,86 @@ function App() {
3133
<Header />
3234
<Routes>
3335
<Route path="/" element={<WelcomePage />} />
34-
<Route path="/molecules" element={<MoleculePage />} />
35-
<Route path="/createmolecule" element={<CreateMoleculePage />} />
36-
<Route path="/crystals" element={<CrystalPage />} />
37-
<Route path="/createcrystal" element={<CreateCystalPage />} />
38-
<Route path="/simulations" element={<SimulationReviewPage />} />
39-
<Route path="/orca" element={<OrcaSubmitPage />} />
36+
<Route
37+
path="/molecules"
38+
element={
39+
<RequireAuth requireOrcaEULA={false}>
40+
<MoleculePage />
41+
</RequireAuth>
42+
}
43+
/>
44+
<Route
45+
path="/createmolecule"
46+
element={
47+
<RequireAuth requireOrcaEULA={false}>
48+
<CreateMoleculePage />
49+
</RequireAuth>
50+
}
51+
/>
52+
<Route
53+
path="/crystals"
54+
element={
55+
<RequireAuth requireOrcaEULA={false}>
56+
<CrystalPage />
57+
</RequireAuth>
58+
}
59+
/>
60+
<Route
61+
path="/createcrystal"
62+
element={
63+
<RequireAuth requireOrcaEULA={false}>
64+
<CreateCystalPage />
65+
</RequireAuth>
66+
}
67+
/>
68+
<Route
69+
path="/simulations"
70+
element={
71+
<RequireAuth requireOrcaEULA={false}>
72+
<SimulationReviewPage />
73+
</RequireAuth>
74+
}
75+
/>
76+
<Route
77+
path="/orca"
78+
element={
79+
<RequireAuth requireOrcaEULA={true}>
80+
<OrcaSubmitPage />
81+
</RequireAuth>
82+
}
83+
/>
84+
<Route
85+
path="/orcaeula"
86+
element={
87+
<RequireAuth requireOrcaEULA={false}>
88+
<OrcaEulaPage />
89+
</RequireAuth>
90+
}
91+
></Route>
4092
<Route
4193
path="/fdmnescrystal"
42-
element={<FdmnesSubmitPage key={"crystal"} isCrystal={true} />}
94+
element={
95+
<RequireAuth requireOrcaEULA={false}>
96+
<FdmnesSubmitPage key={"crystal"} isCrystal={true} />
97+
</RequireAuth>
98+
}
4399
/>
44100
<Route
45101
path="/fdmnesmolecule"
46102
element={
47-
<FdmnesSubmitPage key={"molecule"} isCrystal={false} />
103+
<RequireAuth requireOrcaEULA={false}>
104+
<FdmnesSubmitPage key={"molecule"} isCrystal={false} />
105+
</RequireAuth>
106+
}
107+
/>
108+
<Route
109+
path="/qe"
110+
element={
111+
<RequireAuth requireOrcaEULA={false}>
112+
<QeSubmitPage />
113+
</RequireAuth>
48114
}
49115
/>
50-
<Route path="/qe" element={<QeSubmitPage />} />
51116
</Routes>
52117
<Footer copyright="Diamond Light Source" logo={null} />
53118
</Stack>

web-conexs-client/src/UserContext.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,34 @@ import { Person } from "./models";
33
import { useQuery } from "@tanstack/react-query";
44
import { getUser } from "./queryfunctions";
55

6-
const UserContext = createContext<Person | null>(null);
6+
const UserContext = createContext<Person | null | undefined>(null);
77

88
function UserProvider(props: { children: React.ReactNode }) {
99
const { children } = props;
1010
const query = useQuery({
1111
queryKey: ["user"],
1212
queryFn: getUser,
13+
retry: (failureCount, error) => {
14+
if ("status" in error && error.status == 401) {
15+
//dont retry 401
16+
return false;
17+
}
18+
19+
return failureCount < 2;
20+
},
1321
});
1422

23+
//undefined if pending
24+
let response = undefined;
25+
26+
if (query.isError) {
27+
response = null;
28+
} else {
29+
response = query.data;
30+
}
31+
1532
return (
16-
<UserContext.Provider value={query.data ? query.data : null}>
17-
{children}
18-
</UserContext.Provider>
33+
<UserContext.Provider value={response}>{children}</UserContext.Provider>
1934
);
2035
}
2136

web-conexs-client/src/components/Header.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ export default function Header() {
2727
color="white"
2828
onLogin={handleLogin}
2929
onLogout={handleLogout}
30-
user={user == null ? null : { fedid: user.identifier }}
30+
user={
31+
user == null || user == undefined
32+
? null
33+
: { fedid: user.identifier }
34+
}
3135
/>
3236
<ColourSchemeButton />
3337
</>

0 commit comments

Comments
 (0)