Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ _pkginfo.txt
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Secrets (connection strings, API keys)
**/Secrets.json

# Others
ClientBin/
~$*
Expand Down
4 changes: 2 additions & 2 deletions CommBank-Server/CommBank.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>CommBank_Server</RootNamespace>
Expand All @@ -13,7 +13,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="MongoDB.Driver" Version="2.18.0" />
<PackageReference Include="MongoDB.Driver" Version="2.22.0" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 3 additions & 1 deletion CommBank-Server/Models/Goal.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using MongoDB.Bson;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace CommBank.Models;
Expand All @@ -11,6 +11,8 @@ public class Goal

public string? Name { get; set; }

public string? Icon { get; set; }

public UInt64 TargetAmount { get; set; } = 0;

public DateTime TargetDate { get; set; }
Expand Down
26 changes: 23 additions & 3 deletions CommBank-Server/Program.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
using CommBank.Models;
using System.Text.Json.Serialization;
using CommBank.Models;
using CommBank.Services;
using MongoDB.Driver;

// Prefer TLS 1.2 for MongoDB Atlas (helps avoid "TLS alert: InternalError" on Windows)
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(System.Text.Json.JsonNamingPolicy.CamelCase, allowIntegerValues: false));
});

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("Secrets.json");

var mongoClient = new MongoClient(builder.Configuration.GetConnectionString("CommBank"));
var connectionString = builder.Configuration.GetConnectionString("CommBank");
var mongoClientSettings = MongoClientSettings.FromConnectionString(connectionString);
mongoClientSettings.ServerSelectionTimeout = TimeSpan.FromSeconds(60);
// On Windows, OCSP revocation check can cause TLS "InternalError" handshake failure with Atlas
var ssl = mongoClientSettings.SslSettings ?? new SslSettings();
ssl.CheckCertificateRevocation = false;
mongoClientSettings.SslSettings = ssl;
// Development-only: relax TLS cert validation if Windows still fails (remove in production)
if (builder.Environment.IsDevelopment())
{
mongoClientSettings.AllowInsecureTls = true;
}
var mongoClient = new MongoClient(mongoClientSettings);
var mongoDatabase = mongoClient.GetDatabase("CommBank");

IAccountsService accountsService = new AccountsService(mongoDatabase);
Expand Down
5 changes: 0 additions & 5 deletions CommBank-Server/Secrets.json

This file was deleted.

5 changes: 5 additions & 0 deletions CommBank-Server/Secrets.json.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"ConnectionStrings": {
"CommBank": "mongodb+srv://<username>:<password>@<cluster>.mongodb.net/?appName=YourApp"
}
}
10 changes: 9 additions & 1 deletion CommBank-Server/Services/AccountService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Options;
using CommBank.Models;
using MongoDB.Driver;
using MongoDB.Bson;

namespace CommBank.Services;

Expand All @@ -19,8 +20,15 @@ public async Task<List<Account>> GetAsync() =>
public async Task<Account?> GetAsync(string id) =>
await _accountsCollection.Find(x => x.Id == id).FirstOrDefaultAsync();

public async Task CreateAsync(Account newAccount) =>
public async Task CreateAsync(Account newAccount)
{
if (string.IsNullOrWhiteSpace(newAccount.Id) || !ObjectId.TryParse(newAccount.Id, out _))
{
newAccount.Id = ObjectId.GenerateNewId().ToString();
}

await _accountsCollection.InsertOneAsync(newAccount);
}

public async Task UpdateAsync(string id, Account updatedAccount) =>
await _accountsCollection.ReplaceOneAsync(x => x.Id == id, updatedAccount);
Expand Down
8 changes: 8 additions & 0 deletions CommBank-Server/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"CommBank": "YOUR_CONNECTION_STRING_HERE"
},
"MongoDbSettings": {
"ConnectionString": "YOUR_CONNECTION_STRING_HERE",
"DatabaseName": "commbank"
}
}


181 changes: 181 additions & 0 deletions POSTMAN_TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# Testing the CommBank API with Postman

## 1. Start the server

From the repo root:

```bash
cd CommBank-Server
dotnet run
```

Or run from Visual Studio / Rider. The API will listen on **http://localhost:5203** (or http://localhost:11366 — check the console for the port).

Use this as your **Base URL** in Postman: `http://localhost:5203` (replace with your actual port if different).

---

## 2. Set up Postman

- **Headers:** For POST/PUT, set `Content-Type: application/json` (Postman usually does this when you pick "raw" + "JSON").
- **Body:** For POST/PUT, choose **Body** → **raw** → **JSON**.

---

## 3. Test the main endpoints

### Health check (optional)

- **GET** `http://localhost:5203/swagger/index.html`
Opens Swagger UI in the browser so you can see all endpoints.

---

### Accounts

| Method | URL | Body (for POST/PUT) |
|--------|-----|----------------------|
| GET all | `http://localhost:5203/api/Account` | — |
| GET one | `http://localhost:5203/api/Account/{id}` | — |
| POST | `http://localhost:5203/api/Account` | See below |
| PUT | `http://localhost:5203/api/Account/{id}` | Same shape as POST |
| DELETE | `http://localhost:5203/api/Account/{id}` | — |

**Example POST body (create account):**
```json
{
"name": "My Savings",
"number": 12345678,
"balance": 0,
"accountType": "goalSaver"
}
```
Use `"accountType": "goalSaver"` or `"netBankSaver"`. For GET one / PUT / DELETE, `{id}` must be a 24-character MongoDB ObjectId (e.g. from a previous GET or POST response).

---

### Users

| Method | URL | Body |
|--------|-----|------|
| GET all | `http://localhost:5203/api/User` | — |
| GET one | `http://localhost:5203/api/User/{id}` | — |
| POST | `http://localhost:5203/api/User` | See below |
| PUT | `http://localhost:5203/api/User/{id}` | Same shape |
| DELETE | `http://localhost:5203/api/User/{id}` | — |

**Example POST body (create user — password is hashed by the server):**
```json
{
"name": "Test User",
"email": "test@example.com",
"password": "secret123",
"accountIds": [],
"goalIds": [],
"transactionIds": []
}
```

---

### Auth (login)

- **POST** `http://localhost:5203/api/Auth/Login`

**Body:**
```json
{
"email": "test@example.com",
"password": "secret123"
}
```
- Success: **204 No Content**.
- Wrong email/password: **404 Not Found**.

---

### Goals

| Method | URL | Body |
|--------|-----|------|
| GET all | `http://localhost:5203/api/Goal` | — |
| GET one | `http://localhost:5203/api/Goal/{id}` | — |
| GET by user | `http://localhost:5203/api/Goal/User/{userId}` | — |
| POST | `http://localhost:5203/api/Goal` | See below |
| PUT | `http://localhost:5203/api/Goal/{id}` | Same shape |
| DELETE | `http://localhost:5203/api/Goal/{id}` | — |

**Example POST body:**
```json
{
"name": "Holiday Fund",
"icon": "plane",
"targetAmount": 5000,
"targetDate": "2026-12-31T00:00:00Z",
"balance": 0,
"userId": "PUT_A_USER_OBJECT_ID_HERE"
}
```
`icon` is optional. Get a real `userId` from GET `/api/User`.

---

### Transactions

| Method | URL | Body |
|--------|-----|------|
| GET all | `http://localhost:5203/api/Transaction` | — |
| GET one | `http://localhost:5203/api/Transaction/{id}` | — |
| GET by user | `http://localhost:5203/api/Transaction/User/{userId}` | — |
| POST | `http://localhost:5203/api/Transaction` | See below |
| PUT | `http://localhost:5203/api/Transaction/{id}` | Same shape |
| DELETE | `http://localhost:5203/api/Transaction/{id}` | — |

**Example POST body:**
```json
{
"transactionType": "credit",
"amount": 100.50,
"dateTime": "2026-03-05T12:00:00Z",
"description": "Salary",
"userId": "PUT_A_USER_OBJECT_ID_HERE"
}
```
Use `transactionType`: `"credit"`, `"debit"`, or `"transfer"`. `goalId` and `tagIds` are optional.

---

### Tags

| Method | URL | Body |
|--------|-----|------|
| GET all | `http://localhost:5203/api/Tag` | — |
| GET one | `http://localhost:5203/api/Tag/{id}` | — |
| POST | `http://localhost:5203/api/Tag` | `{ "name": "Groceries" }` |
| PUT | `http://localhost:5203/api/Tag/{id}` | `{ "name": "Food" }` |
| DELETE | `http://localhost:5203/api/Tag/{id}` | — |

---

## 4. Suggested test order

1. **GET** `/api/Account` and `/api/User` — see if the server and DB connection work (empty arrays `[]` is OK).
2. **POST** `/api/User` — create a user; copy the returned `id`.
3. **POST** `/api/Auth/Login` — login with that user’s email/password (expect 204).
4. **POST** `/api/Account` — create an account (use `"accountType": "goalSaver"` or `"netBankSaver"`).
5. **POST** `/api/Goal` — create a goal with the user’s `userId`; optionally include `"icon": "plane"`.
6. **GET** `/api/Goal` or `/api/Goal/User/{userId}` — confirm the goal (and optional `icon`) is returned.
7. **POST** `/api/Transaction` and **POST** `/api/Tag` — then GET to verify.

---

## 5. What to expect

- **GET (list):** `200` with a JSON array (possibly empty `[]`).
- **GET (one):** `200` with one object, or `404` if id not found.
- **POST:** `201 Created` with the created resource (including generated `id`) in the response.
- **PUT:** `204 No Content` on success, `404` if id not found.
- **DELETE:** `204 No Content` on success, `404` if id not found.
- **Login:** `204` on success, `404` if email/password wrong.

If you get **400**, check the request body (valid JSON, correct field names like `accountType`, `transactionType`, and allowed enum values). If you get **500**, check the server console and that MongoDB is reachable (e.g. connection string and Atlas network access).
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Completed all tasks including MongoDB integration and Goal Model modification.
18 changes: 18 additions & 0 deletions expected_response.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Expected Response

Example response from **GET /api/Goal** after completing MongoDB integration and adding the optional `icon` field to the Goal model (real data from this project):

```json
{
"id": "69a9cb57f72212af18e0c289",
"name": "Buy a Car",
"icon": "car-emoji",
"targetAmount": 20000,
"targetDate": "2026-12-31T00:00:00Z",
"balance": 500,
"created": "2026-03-05T21:28:39.0119093+03:00",
"transactionIds": null,
"tagIds": null,
"userId": null
}
```