Skip to content

Commit

Permalink
update branch (#6109)
Browse files Browse the repository at this point in the history
* Fix #5879 radia cylindrical divisions (#5923)

* Fix #5947: move pump_type and rename laser gain tab (#5952)

* Fix #5945: add description for thermal lensing (#5957)

* fix #5937 omega beam centering and error handling (#5959)

* Fix #5944: silas plot units (#5963)

Also fixes new drift and lens module names. Replace chirp with tau_0

* fix #5965 omega fixes (#5966)

- added default values for simWorkflow
- improved layouts
- improved genesis error handling

* Fix #5931: show error if no epics server on start monitor (#5956)

* Fix #5974 radia local cut plane (#5975)

* Fix #5974 - adds center to cut point when specified

---------

Co-authored-by: mkeilman <mkeilman@radiasoft.net>

* fix #3932 include rpnVariables for twissReport cache (#5968)

* fix #5414 added more precision and removed quotes from elegant csv output (#5967)

* fix #5942 match silas results with notebook (#5964)

* Fix #5954: improve silas panel layout (#5960)

* Fix #5596 Add file_lock concurrency protection (#5848)

* Fix #5596 Add file_lock concurrency protection
- Fix #5740 ensure serial greater than incoming and on disk
- Fix #5742 restricted critical sections and removed most
- Fix #5743 migrate_guest_to_persistent_user locks new and guest uid
- Fix #5744 simulation_dir uses lock_user
- Fix #5745 validate version in save_simulation_json
- Fix #5746 removed lock on auth.unchecked_get_user
- Fix #5747 complete_registration passed display_name
- Fix #5749 removed auth_db locking, verified all critical sections
- Fix #5750 thread locking only in flask
- Fix #5751 add auth.create_and_login_user for testing

* fix radiasoft/raydata#62: remove unused options (Simulation Documentation URL, Export as Zip, Python Source) in raydata settings submenu (#5891)

* Fix #5642 pkuinit.restart_or_fail if `_ping_supervisor` fails (#5643)

* fix #5979 fix missing case in plot axis tick formatting (#5987)

* Fix #5978: fixed scale bug in hellweg (#5992)

* fix #5982 use new hellweg binary output format, gamma vs beta (#5997)

* Fix #5983 copy reacts build files into /static (#5984)

* fix #5998 improve hellweg source generation, fixed energy scaling (#5999)

* Fix #5991 - omit one-time eval (#6006)

* Fix #5996: add particles keyword to hellweg (#6001)

* Fix #6018 static_files.gen correctly copies react bundle files (#6019)

* Fix #5943: error message non premium (#5971)

* Fix #5994: make etc/run-jupyterhub.sh work again (#5995)

* Fix #5994: make etc/run-jupyterhub.sh work again

- notebook must now be installed explicitly
- serverextension call is no longer needed with the version of notebook we install
- jupyterhub_debug was removed in favor of feature_config.debug but this
needed to be cascaded in the jupyterhub conf jinja

* fix list

* importable package is with an underscore

* install deps so users dont have to

---------

Co-authored-by: Raven <ravenmarieorourke@gmail.com>

* fix #6029 omega qcall work-around (#6030)

* fix #5734 fixes for email login on react (#5973)

* Fix #5819 radia lock objects (#5969)

* fix #6013 work-around hellweg rf fields bug (#6014)

* Fix #5948 always calculate n0 and n2 using fenics (#6015)

* Fix #6004: change laser pulse units (#6016)

* Fix #6032 - try small instead of subscript (#6035)

* Fix #6044 - replaced segmentationCylRadius field in view (#6045)

Co-authored-by: mkeilman <mkeilman@radiasoft.net>

* fix #5588 omega improvements (#6054)

* Fix #6055 default to tornado api_server in dev mode (#6072)

* Fix #6055 default to tornado api_server in dev mode

* Fix #6074 remove google_tag_manager

---------

Co-authored-by: Raven <ravenmarieorourke@gmail.com>

* Fix #6083: auth.login creates the uid (#6084)

In 791364f the api_authEmailAuthorized
code was changed from passing the user model we acquired based on
searching by the email token to one acquired by searching for the uid
into auth.login.

Previous behavior: 791364f#diff-109de77eab3047455095be7e4c1f5f1d918083adaa02b87d5c862a8e513e8436L61
Behavior introduced in 791364f: 791364f#diff-109de77eab3047455095be7e4c1f5f1d918083adaa02b87d5c862a8e513e8436R89

But, the uid isn't present on the model. auth.login
creates the user and populates the uid. In the case where we have
multiple records in auth_email_user_t without a uid the query would
return all of the records even though we are looking for just one.

This reverts the behavior to what it was previously.

* fix #6077 fix to omega for new opal release (#6090)

* Fix #5936: beamline named amplifier for silas (#6043)

* Fix #6037: replace experimental comparison with new example (#6080)

* Fix #6046: "completed reports" instead of "animation" (#6051)

* fix #6093 silas crystal UI improvements (#6094)

* Fix #6017 improve cloudmc 3d toolbar (#6027)

* fix #5829 implement parallel geometry extraction (#6048)

* Fix #6049 - all object edges now black (#6050)

* Fix #6047 - added axis ratio parameter (#6052)

* fix 6095 increase server_test timeout (#6096)

* fix #6058: raydata start and stop search times pre-populated (#6082)

* Fix #6095 added TestClient.DEFAULT_TIMEOUT_SECS (#6098)

* Fix #6101 increase timeouts in file_lock_test (#6102)

---------

Co-authored-by: Michael Keilman <30352290+mkeilman@users.noreply.github.com>
Co-authored-by: Gurhar Khalsa <49498231+gurhar1133@users.noreply.github.com>
Co-authored-by: Paul Moeller <moeller@radiasoft.net>
Co-authored-by: mkeilman <mkeilman@radiasoft.net>
Co-authored-by: Rob Nagler <github@q33.us>
Co-authored-by: Raven <ravenmarieorourke@gmail.com>
Co-authored-by: Evan Carlin <evan@carlin.com>
  • Loading branch information
8 people authored Jul 13, 2023
1 parent 24fea0f commit 54156ee
Show file tree
Hide file tree
Showing 110 changed files with 2,914 additions and 1,774 deletions.
11 changes: 11 additions & 0 deletions etc/run-jupyterhub.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ END
rm ~/mail/1
fi

# POSIT: versions same in container-beamsim-jupyter/build.sh
# Order is important: jupyterlab-server should be last so it isn't
# overwritten with a newer version.
pip install \
jupyterhub==1.4.2
jupyterhub==1.4.2 \
jupyterlab==3.1.14 \
notebook==6.5.4 \
jupyterlab_server==2.8.2
npm install --global configurable-http-proxy

export SIREPO_FEATURE_CONFIG_MODERATED_SIM_TYPES=jupyterhublogin
export SIREPO_AUTH_ROLE_MODERATION_MODERATOR_EMAIL='vagrant@localhost.localdomain'
export SIREPO_FROM_EMAIL='$USER+support@localhost.localdomain'
Expand Down
13 changes: 7 additions & 6 deletions react/src/component/login/email.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,21 @@ export const LoginEmailConfirm = (props) => {
headers: {
"Content-Type": "application/json"
}
}).then(() =>
}).then(() =>
updateLoginStatusRef(loginStatusRef, appWrapper)
.then(() => navigate(`/react/${appName}`))
.then(() => navigate(`/${appName}`))
)
}

return (
<Container>
{
needCompleteRegistration ? (
needCompleteRegistration === '1' ? (
<LoginExtraInfoForm onComplete={(data) => completeLogin(data)}/>
) : (
<>
<p>Click the button complete the login process.</p>
<Button onClick={() => completeLogin()}>Continue</Button>
<p>Please click the button below complete the login process.</p>
<Button onClick={() => completeLogin()}>Confirm</Button>
</>
)
}
Expand Down Expand Up @@ -70,7 +71,7 @@ export const LoginWithEmail = (props) => {
<Form.Control placeholder="email@example.com" value={email} onChange={(e) => updateEmail(e.target.value)}/>
</Col>
<Col sm="2">
<Button variant="primary" onClick={() => doLogin(email)}>Continue</Button>
<Button variant="primary" onClick={() => doLogin(email)} disabled={! (email && email.match(/^.+@.+\..+$/))}>Continue</Button>
</Col>
</Form.Group>
<Row>
Expand Down
20 changes: 8 additions & 12 deletions react/src/component/login/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const LoginRouter = (props) => {
<Routes>
<Route path={`${routeHelper.localRoutePattern("logout")}/*`} element={<LogoutRoot/>}/>
<Route path={`${routeHelper.localRoutePattern("login")}/*`} element={<LoginRoot/>}/>
<Route path={routeHelper.localRoutePattern("loginConfirm")} element={<LoginConfirm/>}/>
<Route path={routeHelper.localRoutePattern("loginWithEmailConfirm")} element={<LoginConfirm/>}/>
<Route path="*" element={<CatchLoggedOut>{props.children}</CatchLoggedOut>}/>
</Routes>
</CLoginStatusRef.Provider>
Expand Down Expand Up @@ -191,19 +191,12 @@ export const CatchLoggedOut = (props) => {

type LoginConfirmParams = {
token: string,
method: AuthMethod,
needCompleteRegistration: "0" | "1"
}

export const LoginConfirm = (props) => {
let { token, method, needCompleteRegistration } = useParams<LoginConfirmParams>();

switch(method) {
case 'email':
return <LoginEmailConfirm needCompleteRegistration={needCompleteRegistration} token={token}/>
default:
throw new Error(`could not handle login method=${method}`)
}
let { token, needCompleteRegistration } = useParams<LoginConfirmParams>();
return <LoginEmailConfirm needCompleteRegistration={needCompleteRegistration} token={token}/>
}


Expand Down Expand Up @@ -236,11 +229,13 @@ export const LoginExtraInfoForm = (props: { onComplete: ({displayName}) => void
<Form.Label column sm="3">
Your full name
</Form.Label>
<Col sm="9">
<Col sm="7">
<Form.Control value={displayName} onChange={(e) => updateDisplayName(e.target.value)}/>
</Col>
<Col sm="2">
<Button variant="primary" onClick={() => onComplete({ displayName })} disabled={! displayName}>Continue</Button>
</Col>
</Form.Group>
<Button variant="primary" onClick={() => onComplete({ displayName })}>Continue</Button>
</>
)
}
Expand Down Expand Up @@ -286,6 +281,7 @@ export function LogoutRoot(props) {
let navigate = useNavigate();
let appName = useContext(CAppName);
let routeHelper = useContext(CRouteHelper);
useContext(CLoginStatusRef).current.isLoggedIn = false;
useEffect(() => {
fetch(routeHelper.globalRoute("authLogout", { simulation_type: appName })).then(() => navigate(routeHelper.localRoute("root")));
})
Expand Down
7 changes: 7 additions & 0 deletions react/src/layout/report.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ export class SimulationStartLayout extends Layout<SimulationStartConfig, {}> {
<span>{'Simulation Completed'}</span>
<span>{stopwatch.formatElapsedTime()}</span>
<div>{children}</div>
{ simState.alert && <div className="card card-body bg-light">
<pre>{simState.alert}</pre>
</div>
}
{startSimulationButton}
</Stack>
)
Expand All @@ -458,6 +462,9 @@ export class SimulationStartLayout extends Layout<SimulationStartConfig, {}> {
<Stack gap={2}>
<span>{'Simulation Error'}</span>
<span>{stopwatch.formatElapsedTime()}</span>
<div className="card card-body bg-light">
<pre>{simState.alert || simState.error}</pre>
</div>
<div>{children}</div>
{startSimulationButton}
</Stack>
Expand Down
71 changes: 36 additions & 35 deletions sirepo/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,11 @@ def complete_registration(self, name=None):
"""Update the database with the user's display_name and sets state to logged-in.
Guests will have no name.
"""
u = self._qcall_bound_user()
with sirepo.util.THREAD_LOCK:
r = self.user_registration(u)
if self._qcall_bound_method() == METHOD_GUEST and name is not None:
raise AssertionError(
"user name={name} should be None with method={METHOD_GUEST}",
)
r.display_name = name
r.save()
if self._qcall_bound_method() == METHOD_GUEST and name is not None:
raise AssertionError(
"user name={name} should be None with method={METHOD_GUEST}",
)
self.user_registration(self._qcall_bound_user(), display_name=name)
self.qcall.cookie.set_value(_COOKIE_STATE, _STATE_LOGGED_IN)

def cookie_cleaner(self, values):
Expand Down Expand Up @@ -313,25 +309,20 @@ def login(
model=None,
sim_type=None,
display_name=None,
is_mock=False,
want_redirect=False,
):
"""Login the user
Raises an exception if successful, except in the case of methods
Args:
method (module or str): method module (only if is_mock) [None]
method (module or str): method module
uid (str): user to login [None]
model (auth_db.UserDbBase): user to login (overrides uid) [None]
sim_type (str): app to redirect to [None]
display_name (str): to save as the display_name [None]
is_mock (bool): simulated login for srunit.quest_start [False]
want_redirect (bool): http redirect on success [False]
"""
if method is None:
assert is_mock, "only used by srunit.quest_start"
method = METHOD_GUEST
mm = _METHOD_MODULES[method] if isinstance(method, str) else method
self._validate_method(mm, sim_type=sim_type)
guest_uid = None
Expand Down Expand Up @@ -373,11 +364,14 @@ def login(
model.save()
if display_name:
self.complete_registration(self.parse_display_name(display_name))
if is_mock:
return
if sim_type:
if guest_uid and guest_uid != uid:
simulation_db.migrate_guest_to_persistent_user(guest_uid, uid)
self.qcall.auth_db.commit()
simulation_db.migrate_guest_to_persistent_user(
guest_uid,
uid,
qcall=self.qcall,
)
self.login_success_response(sim_type, want_redirect)
assert not mm.AUTH_METHOD_VISIBLE

Expand Down Expand Up @@ -418,6 +412,13 @@ def login_success_response(self, sim_type, want_redirect=False):
sreply=self.qcall.reply_ok(PKDict(authState=self._auth_state())),
)

def create_and_login_user(self):
"""Create a new guest user and log them in
Only useful for testing.
"""
self._create_user(_METHOD_MODULES[METHOD_GUEST], want_login=True)

def need_complete_registration(self, model_or_uid):
"""Does unauthenticated user need to complete registration?
Expand Down Expand Up @@ -467,7 +468,7 @@ def require_auth_basic(self):
if not uid:
raise sirepo.util.WWWAuthenticate()
self.qcall.cookie.set_sentinel()
self.login(m, uid=uid)
self._login_user(m, uid)

def require_email_user(self):
i = self.require_user()
Expand Down Expand Up @@ -514,6 +515,7 @@ def require_user(self):
if m == METHOD_GUEST:
pkdc("guest completeRegistration={}", u)
self.complete_registration()
self.qcall.auth_db.commit()
return u
r = "completeRegistration"
e = "uid={} needs to complete registration".format(u)
Expand All @@ -535,13 +537,10 @@ def reset_state(self):
self._set_log_user()

def unchecked_get_user(self, uid):
with sirepo.util.THREAD_LOCK:
u = self.qcall.auth_db.model("UserRegistration").unchecked_search_by(
uid=uid
)
if u:
return u.uid
return None
u = self.qcall.auth_db.model("UserRegistration").unchecked_search_by(uid=uid)
if u:
return u.uid
return None

def user_dir_not_found(self, user_dir, uid):
"""Called by sirepo.reply when user_dir is not found
Expand All @@ -552,17 +551,15 @@ def user_dir_not_found(self, user_dir, uid):
user_dir (str): directory not found
uid (str): user
"""
with sirepo.util.THREAD_LOCK:
for m in _METHOD_MODULES.values():
u = self._method_user_model(m, uid)
if u:
u.delete()
u = self.qcall.auth_db.model("UserRegistration").unchecked_search_by(
uid=uid
)
for m in _METHOD_MODULES.values():
u = self._method_user_model(m, uid)
if u:
u.delete()
u = self.qcall.auth_db.model("UserRegistration").unchecked_search_by(uid=uid)
if u:
u.delete()
self.reset_state()
self.qcall.auth_db.commit()
pkdlog("user_dir={} uid={}", user_dir, uid)
return self.qcall.reply_redirect_for_app_root()

Expand Down Expand Up @@ -603,7 +600,11 @@ def user_registration(self, uid, display_name=None):
auth.UserRegistration: record (potentially blank)
"""
res = self.qcall.auth_db.model("UserRegistration").unchecked_search_by(uid=uid)
if not res:
if res:
if display_name is not None:
res.display_name = display_name
res.save()
else:
res = self.qcall.auth_db.model(
"UserRegistration",
created=datetime.datetime.utcnow(),
Expand Down
Loading

0 comments on commit 54156ee

Please sign in to comment.