Skip to content

Commit 417248a

Browse files
Merge pull request #977 from microsoft/LogoutFunctionality_Akhileswar
fix: copilot comments resolve code changes
2 parents 08e30c9 + 17b21ed commit 417248a

6 files changed

Lines changed: 40 additions & 57 deletions

File tree

.github/workflows/validate-bicep-params.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,11 @@ jobs:
7777
LOGICAPP_URL: ${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}
7878
ACCELERATOR_NAME: ${{ env.accelerator_name }}
7979
run: |
80-
EMAIL_BODY=$(cat email_body.html)
80+
if [ -f email_body.html ]; then
81+
EMAIL_BODY=$(cat email_body.html)
82+
else
83+
EMAIL_BODY="<p>Bicep parameter validation failed but no HTML report was generated. Check the <a href=\"https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}\">workflow run</a> for details.</p>"
84+
fi
8185
8286
jq -n \
8387
--arg name "${ACCELERATOR_NAME}" \
@@ -93,7 +97,11 @@ jobs:
9397
LOGICAPP_URL: ${{ secrets.EMAILNOTIFICATION_LOGICAPP_URL_TA }}
9498
ACCELERATOR_NAME: ${{ env.accelerator_name }}
9599
run: |
96-
EMAIL_BODY=$(cat email_body.html)
100+
if [ -f email_body.html ]; then
101+
EMAIL_BODY=$(cat email_body.html)
102+
else
103+
EMAIL_BODY="<p>Bicep parameter validation passed. Check the <a href=\"https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}\">workflow run</a> for details.</p>"
104+
fi
97105
98106
jq -n \
99107
--arg name "${ACCELERATOR_NAME}" \

docs/create_new_app_registration.md

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

2121
![Redirect URL](images/azure-app-service-auth-setup/AddRedirectURL.png)
2222

23-
6. Click on `+Add redirect URI`.
23+
6. Click on `+ Add redirect URI`.
2424

2525
![+ Add platform](images/azure-app-service-auth-setup/AddPlatform.png)
2626

infra/scripts/validate_bicep_params.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,14 +671,14 @@ def main() -> int:
671671
# Optional HTML email report
672672
if args.html_output:
673673
scan_dir = str(args.dir) if args.dir else ""
674-
html = generate_html_report(
674+
html_report = generate_html_report(
675675
results,
676676
accelerator_name=args.accelerator_name,
677677
run_url=args.run_url,
678678
scan_dir=scan_dir,
679679
)
680680
args.html_output.parent.mkdir(parents=True, exist_ok=True)
681-
args.html_output.write_text(html, encoding="utf-8")
681+
args.html_output.write_text(html_report, encoding="utf-8")
682682
print(f"HTML report written to {args.html_output}")
683683

684684
has_errors = any(r.has_errors for r in results)

src/App/src/App.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-d
44
import { HomePage, PlanPage } from './pages';
55
import { useWebSocket } from './hooks/useWebSocket';
66
import { useAppDispatch } from './store/hooks';
7-
import { fetchCurrentUser } from './store/slices/appSlice';
7+
import { hydrateCurrentUser } from './store/slices/appSlice';
8+
import { getUserInfoGlobal } from './api/config';
89

910
function App() {
1011
useWebSocket();
1112
const dispatch = useAppDispatch();
1213

1314
useEffect(() => {
14-
dispatch(fetchCurrentUser());
15+
dispatch(hydrateCurrentUser(getUserInfoGlobal()));
1516
}, [dispatch]);
1617

1718
return (

src/App/src/components/auth/LoginButton.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,6 @@ const LoginButton: React.FC<LoginButtonProps> = ({ showName = false }) => {
7373
const userEmail = useAppSelector(state => state.app.userEmail);
7474
const isAuthenticated = Boolean(userId && userId !== 'anonymous');
7575

76-
const login = useCallback(() => {
77-
window.location.href = '/.auth/login/aad';
78-
}, []);
79-
8076
const logout = useCallback(() => {
8177
const logoutUrl = '/.auth/logout?post_logout_redirect_uri=' + encodeURIComponent('/.auth/login/aad');
8278
window.location.href = logoutUrl;

src/App/src/store/slices/appSlice.ts

Lines changed: 24 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/**
22
* App Slice — global application state: config, theme, WebSocket connection, auth.
33
*/
4-
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
4+
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
55
import type { RootState } from '../store';
6-
import { getUserInfo } from '../../api/config';
6+
import { UserInfo } from '../../models';
77

88
export interface AppState {
99
/** Has the runtime config been loaded from /config? */
@@ -29,40 +29,6 @@ const initialState: AppState = {
2929
userEmail: '',
3030
};
3131

32-
export const fetchCurrentUser = createAsyncThunk(
33-
'app/fetchCurrentUser',
34-
async (_arg, { rejectWithValue }) => {
35-
try {
36-
const userInfo = await getUserInfo();
37-
38-
if (!userInfo.user_id) {
39-
return rejectWithValue('No user identity found');
40-
}
41-
42-
// Extract email from claims (preferred_username, email, or UPN)
43-
const userClaims = userInfo.user_claims || [];
44-
let emailVal = userInfo.user_email || '';
45-
for (const claim of userClaims) {
46-
if (claim.typ === 'preferred_username' ||
47-
claim.typ === 'email' ||
48-
claim.typ === 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' ||
49-
claim.typ === 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn') {
50-
emailVal = claim.val;
51-
break;
52-
}
53-
}
54-
55-
return {
56-
userId: userInfo.user_id || 'anonymous',
57-
userName: userInfo.user_first_last_name || '',
58-
userEmail: emailVal,
59-
};
60-
} catch (error) {
61-
return rejectWithValue('Failed to fetch user info');
62-
}
63-
}
64-
);
65-
6632
const appSlice = createSlice({
6733
name: 'app',
6834
initialState,
@@ -76,26 +42,38 @@ const appSlice = createSlice({
7642
setWsConnected(state, action: PayloadAction<boolean>) {
7743
state.wsConnected = action.payload;
7844
},
79-
},
80-
extraReducers: (builder) => {
81-
builder
82-
.addCase(fetchCurrentUser.fulfilled, (state, action) => {
83-
state.userId = action.payload.userId;
84-
state.userName = action.payload.userName;
85-
state.userEmail = action.payload.userEmail;
86-
})
87-
.addCase(fetchCurrentUser.rejected, (state) => {
45+
hydrateCurrentUser(state, action: PayloadAction<UserInfo | null>) {
46+
const userInfo = action.payload;
47+
if (!userInfo || !userInfo.user_id) {
8848
state.userId = 'anonymous';
8949
state.userName = '';
9050
state.userEmail = '';
91-
});
51+
return;
52+
}
53+
state.userId = userInfo.user_id || 'anonymous';
54+
state.userName = userInfo.user_first_last_name || '';
55+
// Extract email from claims
56+
const userClaims = userInfo.user_claims || [];
57+
let emailVal = userInfo.user_email || '';
58+
for (const claim of userClaims) {
59+
if (claim.typ === 'preferred_username' ||
60+
claim.typ === 'email' ||
61+
claim.typ === 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' ||
62+
claim.typ === 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn') {
63+
emailVal = claim.val;
64+
break;
65+
}
66+
}
67+
state.userEmail = emailVal;
68+
},
9269
},
9370
});
9471

9572
export const {
9673
setConfigLoaded,
9774
setIsDarkMode,
9875
setWsConnected,
76+
hydrateCurrentUser,
9977
} = appSlice.actions;
10078

10179
/* ── Granular Selectors ───────────────────────────────────────── */

0 commit comments

Comments
 (0)