Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d2ce4ed
Add missing python requirements file
chriswblake Sep 8, 2025
436464d
make postCreate script executable
chriswblake Sep 8, 2025
680ef5f
Cleanup step 1 wording
chriswblake Sep 8, 2025
253d37a
fix: mongodb script out of date
chriswblake Sep 8, 2025
6eb9f13
Add python to gitignore
chriswblake Sep 8, 2025
ff4f961
fix: missing activities endpoint
chriswblake Sep 8, 2025
0966060
Refine step 1 instructions
chriswblake Sep 8, 2025
6c5ef97
feat: add github cli to dev container
chriswblake Sep 8, 2025
6f1b4fc
fix: incorrect command to check PR reviewers
chriswblake Sep 8, 2025
ecce31d
Refine step 2 instructions
chriswblake Sep 9, 2025
5c4a180
Refine step 3 instructions
chriswblake Sep 9, 2025
bb0f1ef
Refine step 4 instructions
chriswblake Sep 9, 2025
85d88aa
add check step job to step 1
chriswblake Sep 9, 2025
1095292
Switch step 1 images to absolute urls
chriswblake Sep 9, 2025
39b8c44
Switch step 2 images to absolute urls
chriswblake Sep 9, 2025
b98cb76
Switch step 4 images to absolute urls
chriswblake Sep 9, 2025
2fdde78
remove embedded images
chriswblake Sep 9, 2025
296ddd2
fix: incorrect file names
chriswblake Sep 9, 2025
5a96332
refine step 1
chriswblake Sep 9, 2025
3b6daf1
refine step 2
chriswblake Sep 9, 2025
69ce37a
refine step 3
chriswblake Sep 9, 2025
e4c8b67
fix typos in step 1
chriswblake Sep 9, 2025
17e262c
change images to absolute urls, step 2
chriswblake Sep 9, 2025
17e398c
update images to absolute urls, step 3
chriswblake Sep 9, 2025
e4aa2b9
delete relative image files
chriswblake Sep 9, 2025
3fb87b2
refine step 4
chriswblake Sep 9, 2025
0362850
fix: password processing uses mixed hashing methods preventing login
chriswblake Sep 9, 2025
a045d86
Merge branch 'main' into cwb-test-run-adjustments
chriswblake Sep 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/steps/1-step.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ Lets add a simple banner feature for teachers to make announcements and then ask

1. In VS Code, open the source control panel and make note of the uncommitted changes.

1. Hover over the **Changes** section to show various icons. Click the **Code Review** button.
1. Hover over the **Changes** section to show various icons. Click the **Code Review** button and wait a moment for Copilot to add comments.

<img width="300" alt="screenshot of site with announcement banner" src="https://github.com/user-attachments/assets/6c52d550-d67b-4af9-99dd-e181695a4933"/>

> 💡 **TIP:** There are 3 levels of review available: `unstaged changes` and `staged changes` and `uncommitted changes`

1. In VS Code, open the **Comments** panel to find a list of review feedback from Copilot.
1. Expand the **Comments** panel to find a list of review feedback from Copilot.

<img width="300" alt="screenshot of problems control panel with comments from Copilot" src="https://github.com/user-attachments/assets/64c5efb6-9071-4511-b2a2-2dc85c9e929b"/>

Expand Down
10 changes: 7 additions & 3 deletions .github/steps/2-step.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,23 @@ For more information, see the [GitHub Copilot code review documentation](https:/

### ⌨️ Activity: Request a review

1. If needed, open a another tab and for this exercise repository.
1. If needed, open a another tab for this exercise repository.

1. Start a new pull request. Enter the following details and click the **Create pull request** button.

- **compare:** `add-announcement-banner`
- **target:** `main`
- **title:** `Add Announcement Banner`
- **title:** `Add announcement banner`

1. In the right-side details area, find the **Reviewers** menu. Click on the **settings icon** to show a list of available reviewers and select **Copilot**.

<img width="300" alt="screenshot of reviewers menu" src="https://github.com/user-attachments/assets/0f9f2e86-51b7-4542-82a1-afb6a22ab3ca"/>

1. Wait a moment for Copilot to review the changes and add comments to your pull request.
1. Wait a moment for Copilot to review the changes and add comments to your pull request. Notice an entry was added to the conversation log.

<img width="300" alt="new log entry - requested review from copilot" src="https://github.com/user-attachments/assets/3e522bda-e68e-4469-93f4-a7ad103cca97"/>

<img width="300" alt="new log entry - copilot's review summary" src="https://github.com/user-attachments/assets/0a870950-560e-4df8-80d5-2b93f1be99ab"/>

1. With the review requested, wait a moment for Mona to check your work, provide feedback, and share the next lesson.

Expand Down
15 changes: 12 additions & 3 deletions .github/steps/3-step.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The school's coding standards are crucial for maintaining the activities website

### 📖 Theory: Repository Custom Instructions

Repository custom instructions allow you to provide Copilot with context about your project standards and preferences. By creating instruction files, you can ensure Copilot's suggestions consistently follow your team's conventions and focus on your specific requirements.
Repository custom instructions allow you to provide Copilot with context about your project standards and preferences. By creating instruction files, you can ensure Copilot's suggestions consistently follow your team's conventions and focus on your specific requirements. You can even have copilot analyze your project and [generate instructions](https://code.visualstudio.com/docs/copilot/customization/custom-instructions#_generate-an-instructions-file-for-your-workspace) for you!

**Types of Instructions:**

Expand Down Expand Up @@ -66,7 +66,9 @@ Let's customize Copilot's review considerations by adding custom instructions.

Let's create specific Copilot's review considerations for the frontend and backend.

1. Create `.github/instructions/frontend.instructions.md` for and add the following content.
1. Create `.github/instructions/frontend.instructions.md` and add the following guidelines.

> ❗️ **Important**: Make sure to put file-specific instructions in the `.github/instructions/` folder, not the `.github/` folder.

> ❗️ **Important**: Make sure to put file-specific instructions in the `.github/instructions/` folder, not the `.github/` folder.

Expand All @@ -82,7 +84,7 @@ Let's create specific Copilot's review considerations for the frontend and backe
- Validate HTML structure and semantic elements
```

1. Create `.github/instructions/backend.instructions.md` for server-side guidelines:
1. Create `.github/instructions/backend.instructions.md` and add the following guidelines:

```markdown
---
Expand All @@ -100,6 +102,9 @@ applyTo: "backend/**/*,*.py"

1. Commit and push the changes.

> [!TIP]
> VS Code has a built-in commands to help manage instructions. Try opening the command pallette and searching for `instructions`.

### ⌨️ Activity: Request another review

With our new instructions defined, Copilot now has a better idea of what is important for our project. Let's ask for another review.
Expand All @@ -108,6 +113,10 @@ With our new instructions defined, Copilot now has a better idea of what is impo

1. In the top right, find the **Reviewers** menu and **Re-request review** button next to **Copilot**. Click it and wait a moment for Copilot to add comments on the pull request.

<img width="300" alt="screenshot of re-review button" src="https://github.com/user-attachments/assets/e6fdc77c-3323-466b-8d30-f9a8eb543f3f"/>

> 🪧 **Note:** If you are too quick after pushing new commits, you may have to wait a moment for the button to appear.

1. Observe that Copilot's feedback now differs from the previous review.

1. With the review requested, wait a moment for Mona to check your work, provide feedback, and share the next lesson.
Expand Down
30 changes: 15 additions & 15 deletions .github/steps/4-step.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ For more information, see the [repository rulesets documentation](https://docs.g
- **Ruleset Name**: `Require Copilot Reviews`
- **Enforcement Status**: `Active`

1. Under **Target branches**, add protections for the `main` branch:
1. Under **Target branches**, add protections for the `main` branch.

1. Click **Add target** and **Include default branch**.
1. Click **Add target** and **Include by pattern**.
Expand All @@ -62,29 +62,38 @@ For more information, see the [repository rulesets documentation](https://docs.g

1. Merge the pull request.

> 💡 **Tip**: If the **Merge pull request** button doesn't activate, check for unresolved conversations in the outdated comments.
> 🪧 **Note**: If the **Merge pull request** button doesn't activate, check for unresolved conversations in the outdated comments.

1. With the pull requested merged, wait a moment for Mona to check your work, provide feedback, and share the next lesson.
1. With the pull request merged, wait a moment for Mona to check your work, provide feedback, and share the next lesson.

### ⌨️ Activity: (optional) Test required review

Not ready to finish yet? Are you concerned by the hard coded announcement banner?

Us too! So, let's fix it! 🧑‍🚀🚀

1. In VS Code, switch back to the `main` branch, pull the merged changes, and delete the `add-announcement-banner` branch.

1. Create a new branch with the following name.

```txt
enable-editing-announcements
```

1. Ask copilot to upgrade our new Announcements feature.
1. Open the Copilot Chat panel and ask Copilot to upgrade our new Announcements feature.

> ![Static Badge](https://img.shields.io/badge/-Prompt-text?style=social&logo=github%20copilot)
>
> ```prompt
> The Announcement feature should not be hard coded.
>
> - Make it driven from the database.
> - Allow signed in teachers to create and modify announcements.
> - Add a button in the header that opens a dialog window. It lists all existing announcements and has controls to add/modify/delete them.
> - Only signed in users have access to manage announcements.
> - Announcements require an expiration date. Start date is optional.
> - Add an example message to the database initialization.
> - Don't worry about unit testing.
> - Make it pretty with a good UI/UX experience.
> ```

1. (optional) Run the application to test the changes.
Expand All @@ -105,13 +114,4 @@ For more information, see the [repository rulesets documentation](https://docs.g

1. Merge the pull request.

1. With the review requested, wait a moment for Mona to check your work, provide feedback, and share the next lesson.

<!--
<details>
<summary>Having trouble? 🤷</summary><br/>

- ???

</details>
-->
1. Nice work! You are all done, again! 🎉
6 changes: 3 additions & 3 deletions .github/workflows/1-step.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ jobs:
continue-on-error: true
uses: skills/action-keyphrase-checker@v1.1.0
with:
text-file: rc/static/index.html
text-file: src/static/index.html
keyphrase: announcement

- name: Check style.css for keyphrase
id: check-style-css
continue-on-error: true
uses: skills/action-keyphrase-checker@v1.1.0
with:
text-file: rc/static/index.html
text-file: src/static/style.css
keyphrase: announcement-banner

- name: Update comment - step results
Expand All @@ -79,7 +79,7 @@ jobs:
edit-mode: replace
file: exercise-toolkit/markdown-templates/step-feedback/step-results-table.md
vars: |
step_number: 2
step_number: 1
results_table:
- description: "announcement added to index.html"
passed: ${{ steps.check-index-html.outcome == 'success' }}
Expand Down
30 changes: 25 additions & 5 deletions src/backend/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

from pymongo import MongoClient
from argon2 import PasswordHasher
from argon2 import PasswordHasher, exceptions as argon2_exceptions

# Connect to MongoDB
client = MongoClient('mongodb://localhost:27017/')
Expand All @@ -12,23 +12,44 @@
teachers_collection = db['teachers']

# Methods


def hash_password(password):
"""Hash password using Argon2"""
ph = PasswordHasher()
return ph.hash(password)


def verify_password(hashed_password: str, plain_password: str) -> bool:
"""Verify a plain password against an Argon2 hashed password.

Returns True when the password matches, False otherwise.
"""
ph = PasswordHasher()
try:
ph.verify(hashed_password, plain_password)
return True
except argon2_exceptions.VerifyMismatchError:
return False
except Exception:
# For any other exception (e.g., invalid hash), treat as non-match
return False


def init_database():
"""Initialize database if empty"""

# Initialize activities if empty
if activities_collection.count_documents({}) == 0:
for name, details in initial_activities.items():
activities_collection.insert_one({"_id": name, **details})

# Initialize teacher accounts if empty
if teachers_collection.count_documents({}) == 0:
for teacher in initial_teachers:
teachers_collection.insert_one({"_id": teacher["username"], **teacher})
teachers_collection.insert_one(
{"_id": teacher["username"], **teacher})


# Initial database if empty
initial_activities = {
Expand Down Expand Up @@ -172,7 +193,7 @@ def init_database():
"display_name": "Ms. Rodriguez",
"password": hash_password("art123"),
"role": "teacher"
},
},
{
"username": "mchen",
"display_name": "Mr. Chen",
Expand All @@ -186,4 +207,3 @@ def init_database():
"role": "admin"
}
]

26 changes: 11 additions & 15 deletions src/backend/routers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,44 @@

from fastapi import APIRouter, HTTPException
from typing import Dict, Any
import hashlib

from ..database import teachers_collection
from ..database import teachers_collection, verify_password

router = APIRouter(
prefix="/auth",
tags=["auth"]
)

def hash_password(password):
"""Hash password using SHA-256"""
return hashlib.sha256(password.encode()).hexdigest()

@router.post("/login")
def login(username: str, password: str) -> Dict[str, Any]:
"""Login a teacher account"""
# Hash the provided password
hashed_password = hash_password(password)

# Find the teacher in the database
teacher = teachers_collection.find_one({"_id": username})

if not teacher or teacher["password"] != hashed_password:
raise HTTPException(status_code=401, detail="Invalid username or password")


# Verify password using Argon2 verifier from database.py
if not teacher or not verify_password(teacher.get("password", ""), password):
raise HTTPException(
status_code=401, detail="Invalid username or password")

# Return teacher information (excluding password)
return {
"username": teacher["username"],
"display_name": teacher["display_name"],
"role": teacher["role"]
}


@router.get("/check-session")
def check_session(username: str) -> Dict[str, Any]:
"""Check if a session is valid by username"""
teacher = teachers_collection.find_one({"_id": username})

if not teacher:
raise HTTPException(status_code=404, detail="Teacher not found")

return {
"username": teacher["username"],
"display_name": teacher["display_name"],
"role": teacher["role"]
}
}
Loading