Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
138b011
♻️Refactor: Introduce UserProfile service & multi-event model
indcoder Jan 13, 2026
f62960c
Add Azure Container Apps support to AppHost
indcoder Jan 16, 2026
6854137
Replace registration project restore with user profile
indcoder Jan 16, 2026
2149101
Fix path for UserProfile project restore command
indcoder Jan 16, 2026
c79de19
Update dev env and Scalar API config; add ENC0118 note
indcoder Jan 19, 2026
165fa53
Restrict "Schedule Event" button to VisageAdmin users
indcoder Jan 19, 2026
6a875a0
Merge branch 'rf_registrant2user' of github.com:HackerspaceMumbai/Vis…
indcoder Jan 19, 2026
f4143ca
Initial plan
Copilot Jan 20, 2026
5ff5ab9
Fix critical security vulnerabilities in authentication and authoriza…
Copilot Jan 20, 2026
749c098
Fix authorization bypass in UserProfile endpoints and use migrations
Copilot Jan 20, 2026
1595d27
Fix frontend/backend inconsistencies and documentation
Copilot Jan 20, 2026
7127758
Align frontend RegistrationStatus enum with backend
Copilot Jan 20, 2026
c846821
Document required database migration fixes
Copilot Jan 20, 2026
6cdb530
Fix EventRegistration default status to use Pending
Copilot Jan 20, 2026
16d408b
Add documentation for known limitations and edge cases
Copilot Jan 20, 2026
77f9502
Restore [Required] attribute on GovtId field
Copilot Jan 20, 2026
2730d42
Fix CodeQL security issues: prevent information disclosure
Copilot Jan 21, 2026
a1fa7b6
Improve logging security: use proper logger and restrict debug logs
Copilot Jan 21, 2026
8088462
Refine exception handling and JWT validation logic
Copilot Jan 21, 2026
4777314
Merge pull request #214 from HackerspaceMumbai/copilot/fix-code-revie…
indcoder Jan 21, 2026
9b7e555
🧪 ci: refine test selection and remove workload restore
indcoder Jan 22, 2026
53fcb45
chore(🔨):Refactor DB init: dev uses EnsureCreated, prod uses migrate
indcoder Jan 23, 2026
be20326
Update services/Visage.Services.Eventing/Program.cs
indcoder Jan 24, 2026
fbe06b9
Update tests/Visage.Test.Aspire/QUICKSTART.md
indcoder Jan 24, 2026
320c624
Enhance event reg security, concurrency, and feedback
indcoder Jan 24, 2026
9822221
Update QUICKSTART.md setup instructions formatting
indcoder Jan 24, 2026
1d2b189
Initial plan
Copilot Jan 24, 2026
9f3eaa4
Implement security and data integrity fixes across Eventing and UserP…
Copilot Jan 24, 2026
7074291
Merge pull request #218 from HackerspaceMumbai/copilot/update-event-r…
indcoder Jan 24, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ jobs:
dotnet restore Visage.FrontEnd/Visage.FrontEnd.Web.Client/Visage.FrontEnd.Web.Client.csproj
dotnet restore Visage.FrontEnd/Visage.FrontEnd.Shared/Visage.FrontEnd.Shared.csproj
dotnet restore services/Visage.Services.Eventing/Visage.Services.Eventing.csproj
dotnet restore Visage.Services.Registrations/Visage.Services.Registrations.csproj
dotnet restore Visage.Services.UserProfile/Visage.Services.UserProfile.csproj
7 changes: 3 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ jobs:
cache: true
cache-dependency-path: '**/packages.lock.json'

- name: Restore .NET workloads
run: dotnet workload restore
# CI runs on ubuntu; avoid restoring MAUI workloads (iOS/MacCatalyst) which require non-Linux SDK packs.

- name: Display dotnet version
run: dotnet --version
Expand All @@ -32,7 +31,7 @@ jobs:
fi

- name: Run default smoke tests
run: dotnet test --filter "Category=Smoke"
run: dotnet test --project tests/Visage.Test.Aspire/Visage.Test.Aspire.csproj -- --treenode-filter "/*/*/*/*[Category=Smoke]"
Comment on lines 33 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Check the test framework and dependencies in the Aspire test project
cat -n tests/Visage.Test.Aspire/Visage.Test.Aspire.csproj | head -50

Repository: HackerspaceMumbai/Visage

Length of output: 1950


🏁 Script executed:

# Search for any test framework references
rg -i "(nunit|xunit|mstest)" tests/Visage.Test.Aspire/ -g "*.csproj"

Repository: HackerspaceMumbai/Visage

Length of output: 50


🏁 Script executed:

# Look for Category or TestCategory attributes
rg -n "\[(Category|TestCategory|Trait)\(" tests/Visage.Test.Aspire/ -g "*.cs" -A 1

Repository: HackerspaceMumbai/Visage

Length of output: 2010


🏁 Script executed:

# Check if there are Smoke or RequiresAuth test markers
rg -n "(Smoke|RequiresAuth)" tests/ -g "*.cs"

Repository: HackerspaceMumbai/Visage

Length of output: 1152


🏁 Script executed:

# Examine the workflow file to see both lines 33-34 and 65-66
sed -n '30,70p' .github/workflows/tests.yml

Repository: HackerspaceMumbai/Visage

Length of output: 1465


🏁 Script executed:

# Search for any existing dotnet test invocations in the repo to see how filtering is done
rg -n "dotnet test.*--filter" . -g "*.yml" -g "*.yaml" -g "*.sh"

Repository: HackerspaceMumbai/Visage

Length of output: 50


🏁 Script executed:

# Check if there are any TUnit configuration files or documentation
fd -n "tunit" -i . --type f

Repository: HackerspaceMumbai/Visage

Length of output: 298


🏁 Script executed:

# Look for TUnit filter usage in test files or scripts
rg -n "filter" tests/Visage.Test.Aspire/ -g "*.cs" | head -20

Repository: HackerspaceMumbai/Visage

Length of output: 737


🏁 Script executed:

# Check TUnit package version and documentation reference in project files
rg "TUnit" . -g "*.csproj" -g "*.json"

Repository: HackerspaceMumbai/Visage

Length of output: 1137


Replace --treenode-filter with --filter for TUnit compatibility.
TUnit uses --filter "Category=<value>" syntax, not --treenode-filter. The test framework is TUnit 1.5.70, and the categories (Smoke, RequiresAuth) exist in the codebase. The --project flag is valid. However, the filter command will fail or silently skip filtering with the current syntax.

Corrected filter syntax
-        run: dotnet test --project tests/Visage.Test.Aspire/Visage.Test.Aspire.csproj -- --treenode-filter "/*/*/*/*[Category=Smoke]"
+        run: dotnet test --project tests/Visage.Test.Aspire/Visage.Test.Aspire.csproj --filter "Category=Smoke"

Also applies to: 65-66 (replace --treenode-filter "/*/*/*/*[Category=RequiresAuth]" with --filter "Category=RequiresAuth")

🤖 Prompt for AI Agents
In @.github/workflows/tests.yml around lines 33 - 34, The workflow step named
"Run default smoke tests" (and the similar step for RequiresAuth) is using the
unsupported --treenode-filter option; replace it with the TUnit-compatible flag
--filter and use the TUnit filter expression format (e.g. --filter
"Category=Smoke" and --filter "Category=RequiresAuth") so dotnet test --project
... uses the correct filtering syntax for TUnit 1.5.70.


requires-auth-tests:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -64,4 +63,4 @@ jobs:
fi

- name: Run RequiresAuth tests
run: dotnet test --filter "Category=RequiresAuth"
run: dotnet test --project tests/Visage.Test.Aspire/Visage.Test.Aspire.csproj -- --treenode-filter "/*/*/*/*[Category=RequiresAuth]"
48 changes: 48 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ This guide provides information on filing issues and guidelines for open source

[How Can I Contribute?](#how-can-i-contribute)

[Testing (TUnit)](#testing-tunit)

## Code of Conduct

Keep our community approachable and respectable. This project and everyone participating in it is governed by the [Hackerspace Mumbai's Code of Conduct](https://github.com/HackerspaceMumbai/HackerspaceMumbai/blob/master/CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to community@hackmum.in.
Expand Down Expand Up @@ -62,4 +64,50 @@ PR are always welcome, even if they only contain small fixes like typos or a few

If its hacktoberfest related, the maintainer will suitably label the PR as hacktoberfest.

## Testing (TUnit)

Visage uses **TUnit** for automated tests.

### Running tests

```powershell
# Run all tests

dotnet test
```

### Selecting tests (TUnit `--treenode-filter`)

TUnit supports selecting tests using `--treenode-filter`.

Filter format: `/<Assembly>/<Namespace>/<Class name>/<Test name>` (wildcards supported with `*`).

```powershell
# Run all tests in a class

dotnet test --project tests\Visage.Test.Aspire\Visage.Test.Aspire.csproj --treenode-filter "/*/*/HealthEndpointTests/*"

# Run a single test by name

dotnet test --project tests\Visage.Test.Aspire\Visage.Test.Aspire.csproj --treenode-filter "/*/*/*/All_Http_Resources_Should_Have_Health_Endpoints"
```

### Selecting by category

Many tests use `[Category("...")]` (for example `RequiresAuth`, `AspireHealth`, `E2E`).

TUnit supports property-based filters:

```powershell
# Run RequiresAuth tests

dotnet test --project tests\Visage.Test.Aspire\Visage.Test.Aspire.csproj --treenode-filter "/*/*/*/*[Category=RequiresAuth]"

# Exclude RequiresAuth tests

dotnet test --project tests\Visage.Test.Aspire\Visage.Test.Aspire.csproj --treenode-filter "/*/*/*/*[Category!=RequiresAuth]"
```

> **Note:** Avoid vstest `--filter` guidance for TUnit runs; prefer `--treenode-filter`.

**Looking forward to your contribution 🙏**
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<PackageVersion Include="Aspire.Hosting.JavaScript" Version="13.1.0" />
<PackageVersion Include="Aspire.Hosting.SqlServer" Version="13.1.0" />
<PackageVersion Include="Aspire.Hosting.Testing" Version="13.1.0" />
<PackageVersion Include="Aspire.Hosting.Azure.AppContainers" Version="13.1.0" />
<!-- Microsoft ASP.NET Core packages -->
<PackageVersion Include="Aspire.Microsoft.EntityFrameworkCore.SqlServer" Version="13.1.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.1" />
Expand Down
178 changes: 178 additions & 0 deletions MIGRATION_FIXES_NEEDED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Database Migration Fixes Required

## Overview
The `InitialUserProfile` migration (20260110145754) has several issues that need to be corrected with a new migration.

## Issues Identified in Code Review

### 1. Cross-Service Coupling - Event Table
**Problem**: The UserProfile service migration creates an `Event` table, which should only be managed by the Eventing service.

**Impact**:
- Violates microservice boundaries
- Creates CASCADE delete dependencies across services
- Causes data synchronization issues

**Fix**: Remove the Event table from UserProfile database. The EventId in EventRegistrations should be a simple string reference without a foreign key constraint.

### 2. Missing Auth0Subject Column in Users Table
**Problem**: The Users table is missing the `Auth0Subject` column, which is defined in `Visage.Shared.Models.User.cs` with `[StringLength(255)]`.

**Impact**:
- Runtime errors when persisting user data
- Authentication flow breaks
- Cannot enforce authenticated ownership

**Fix**: Add `Auth0Subject` column:
```sql
Auth0Subject nvarchar(255) NOT NULL
```

### 3. Missing Auth0Subject Column in EventRegistrations Table
**Problem**: The EventRegistrations table is missing the `Auth0Subject` column, which is defined in `Visage.Shared.Models.EventRegistration.cs`.

**Impact**:
- Cannot enforce authenticated ownership for registrations
- Eventing service EventDB expects this column (see indexes at lines 72-74 of EventDB.cs)
- Schema mismatch between services

**Fix**: Add `Auth0Subject` column:
```sql
Auth0Subject nvarchar(255) NOT NULL
```

## Recommended Migration Steps

### Option 1: Create New Migration (Recommended)
```bash
# Navigate to UserProfile service directory
cd Visage.Services.UserProfile

# Enable aspire exec feature
aspire config set features.execCommandEnabled true

# Create the migration
aspire exec --resource userprofile-api --workdir /path/to/Visage.Services.UserProfile -- dotnet ef migrations add FixCrossServiceCouplingAndAuth0Subject
```

### Option 2: Manual Migration File
If EF Core tools are not available, create a new migration file manually:

**Filename**: `Visage.Services.UserProfile/Migrations/YYYYMMDDHHMMSS_FixCrossServiceCouplingAndAuth0Subject.cs`

**Up Method**:
```csharp
protected override void Up(MigrationBuilder migrationBuilder)
{
// Remove FK constraint from EventRegistrations to Event
migrationBuilder.DropForeignKey(
name: "FK_EventRegistrations_Event_EventId",
table: "EventRegistrations");

// Drop the Event table (should only exist in Eventing service)
migrationBuilder.DropTable(
name: "Event");

// Add Auth0Subject to Users table
migrationBuilder.AddColumn<string>(
name: "Auth0Subject",
table: "Users",
type: "nvarchar(255)",
maxLength: 255,
nullable: false,
defaultValue: "");

// Add Auth0Subject to EventRegistrations table
migrationBuilder.AddColumn<string>(
name: "Auth0Subject",
table: "EventRegistrations",
type: "nvarchar(255)",
maxLength: 255,
nullable: false,
defaultValue: "");
}
```

**Down Method**:
```csharp
protected override void Down(MigrationBuilder migrationBuilder)
{
// Remove Auth0Subject columns
migrationBuilder.DropColumn(
name: "Auth0Subject",
table: "EventRegistrations");

migrationBuilder.DropColumn(
name: "Auth0Subject",
table: "Users");

// Recreate Event table
migrationBuilder.CreateTable(
name: "Event",
columns: table => new
{
Id = table.Column<string>(type: "nchar(26)", fixedLength: true, maxLength: 26, nullable: false),
Title = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Type = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
Description = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
StartDate = table.Column<DateOnly>(type: "date", nullable: false),
StartTime = table.Column<TimeOnly>(type: "time", nullable: false),
EndDate = table.Column<DateOnly>(type: "date", nullable: false),
EndTime = table.Column<TimeOnly>(type: "time", nullable: false),
Location = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
CoverPicture = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
AttendeesPercentage = table.Column<decimal>(type: "decimal(18,2)", nullable: true),
Hashtag = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
Theme = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Event", x => x.Id);
});

// Recreate FK constraint
migrationBuilder.AddForeignKey(
name: "FK_EventRegistrations_Event_EventId",
table: "EventRegistrations",
column: "EventId",
principalTable: "Event",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
```

## Testing After Migration

1. Verify the migration applies successfully:
```bash
aspire exec --resource userprofile-api --workdir /path/to/Visage.Services.UserProfile -- dotnet ef database update
```

2. Run integration tests:
```bash
dotnet test tests/Visage.Test.Aspire/Visage.Test.Aspire.csproj
```

3. Verify User creation works with Auth0Subject:
```bash
# Test the POST /api/users endpoint with Auth0 authentication
```

4. Verify Event registration works:
```bash
# Test the POST /api/registrations endpoint
```

## Related Files
- `/home/runner/work/Visage/Visage/Visage.Services.UserProfile/Migrations/20260110145754_InitialUserProfile.cs`
- `/home/runner/work/Visage/Visage/Visage.Shared/Models/User.cs` (line 22: Auth0Subject property)
- `/home/runner/work/Visage/Visage/Visage.Shared/Models/EventRegistration.cs` (line 35: Auth0Subject property)
- `/home/runner/work/Visage/Visage/services/Visage.Services.Eventing/EventDB.cs` (lines 72-74: Auth0Subject indexes)

## Status
⚠️ **Action Required**: These database schema changes cannot be completed in this environment due to missing EF Core tooling. They need to be applied in the actual development environment where:
- EF Core tools are installed
- Aspire CLI is available
- Database connections are configured

All other code review suggestions have been addressed in the current PR.
Loading
Loading