Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
04388dd
MàJ des dépendances de test
louisdevie Apr 13, 2025
ed9dcac
MàJ du copyright
louisdevie Apr 16, 2025
71c5773
:
louisdevie Apr 16, 2025
2e74ada
Merge remote-tracking branch 'refs/remotes/origin/main' into feature/…
louisdevie Apr 17, 2025
8a6a002
HashAndSaltMapper plus simple
louisdevie Apr 17, 2025
3002b15
chore: MàJ de KiwiQuery
louisdevie Apr 17, 2025
f967c31
fix: correction des validateurs pour `PartialClient` et `PartialSameS…
louisdevie Apr 17, 2025
d8a1fd5
feat: définition complète de la classe `PricingType`
louisdevie Apr 17, 2025
67c458b
style: ajustement automatic des namespaces
louisdevie Apr 17, 2025
92d14c7
fix: sorti la classe `Builtins` de son namespace
louisdevie Apr 18, 2025
a12baed
test: ajout des tests de tarifs, correction d'un test de catégorie
louisdevie Apr 18, 2025
b0f1200
Installation de Multiflag v2
louisdevie May 2, 2025
d75a8f0
utilisation de multiflag pour les permissions
louisdevie May 2, 2025
795f7c2
feat: renommer `PricingType` en `PriceList`
louisdevie May 3, 2025
ae37c0a
ci: séparation des tests et du déploiement
louisdevie May 10, 2025
0202e71
Lecture des tarifs
louisdevie May 10, 2025
b9e9383
fix: utiliser uint pour SameSignOnScope
louisdevie May 10, 2025
d42933d
feat: API des tarifs terminée
louisdevie May 10, 2025
455f2d9
fix: renommer les members de `Availability`
louisdevie May 10, 2025
34e0200
fix: MàJ des permissions
louisdevie May 11, 2025
6365015
fix: implémentation du dao pour mariadb
louisdevie May 11, 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
34 changes: 34 additions & 0 deletions .github/workflows/deploiement.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Déploiement

on:
push:
tags: [ '**' ]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build WebService --no-restore /warnaserror -c Release
- name: Setup Python
uses: actions/setup-python@v4.7.1
with:
python-version: '3.11'
- name: Install Paramiko
run: python3 -m pip install paramiko
- name: Deploy build
env:
DEPLOY_HOSTNAME: ${{ secrets.DEPLOY_HOSTNAME }}
DEPLOY_USERNAME: ${{ secrets.DEPLOY_USERNAME }}
DEPLOY_PASSWORD: ${{ secrets.DEPLOY_PASSWORD }}
run: python3 .deployment/galliumplus-deploy
Original file line number Diff line number Diff line change
@@ -1,45 +1,12 @@
name: Vérifications

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build WebService --no-restore /warnaserror -c Release
- name: Setup Python
uses: actions/setup-python@v4.7.1
with:
python-version: '3.11'
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- name: Install Paramiko
run: python3 -m pip install paramiko
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- name: Deploy build
env:
DEPLOY_HOSTNAME: ${{ secrets.DEPLOY_HOSTNAME }}
DEPLOY_USERNAME: ${{ secrets.DEPLOY_USERNAME }}
DEPLOY_PASSWORD: ${{ secrets.DEPLOY_PASSWORD }}
run: python3 .deployment/galliumplus-deploy
if: github.event_name == 'push' && github.ref == 'refs/heads/main'

unit-tests:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
env:
GALLIUM_ENV: test
GALLIUM_HTTP: 5080
Expand All @@ -51,13 +18,16 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
dotnet-version: 8.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build WebService --no-restore /warnaserror -c Release
- name: Run unit tests
run: dotnet test CoreTests

api-tests:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
env:
GALLIUM_ENV: test
GALLIUM_HTTP: 5080
Expand Down
2 changes: 1 addition & 1 deletion .tests/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@

if __name__ == "__main__":
decimal.DefaultContext.prec = 2
Launcher.launch("1.2.0")
Launcher.launch("1.3.0")
4 changes: 2 additions & 2 deletions .tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
certifi==2023.5.7
certifi==2025.1.31
charset-normalizer==3.1.0
idna==3.4
idna==3.10
psutil==5.9.5
PyJWT==2.8.0
requests==2.32.3
Expand Down
5 changes: 3 additions & 2 deletions .tests/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from .access_tests import AccessTests
from .application_tests import ApplicationTests
from .category_tests import CategoryTests
from .order_tests import OrderTests
from .pricing_tests import PricingTests
from .product_tests import ProductTests
from .role_tests import RoleTests
from .order_tests import OrderTests
from .user_tests import UserTests
from .access_tests import AccessTests
4 changes: 2 additions & 2 deletions .tests/tests/access_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def test_login_permissions_normal(self):
self.expect(president_session)
.to.have.an_item("permissions")
.of.type(int)
.that._is.equal_to(2047) # president, full permissions
.that._is.equal_to(4095) # president, full permissions
)

member_token = self.expect(member_session).to.have.an_item("token").value
Expand Down Expand Up @@ -217,7 +217,7 @@ def test_login_permissions_minimum(self):
self.expect(president_session)
.to.have.an_item("permissions")
.of.type(int)
.that._is.equal_to(2047) # president, full permissions
.that._is.equal_to(4095) # president, full permissions
)

member_token = self.expect(member_session).to.have.an_item("token").value
Expand Down
6 changes: 3 additions & 3 deletions .tests/tests/audit_tests_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
"PriceAdded": 0x161,
"PriceModified": 0x162,
"PriceDeleted": 0x163,
"PricingTypeAdded": 0x171,
"PricingTypeModified": 0x172,
"PricingTypeDeleted": 0x173,
"PriceListAdded": 0x171,
"PriceListModified": 0x172,
"PriceListDeleted": 0x173,
"RoleAdded": 0x181,
"RoleModified": 0x182,
"RoleDeleted": 0x183,
Expand Down
4 changes: 2 additions & 2 deletions .tests/tests/category_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def test_category_create(self):
# Informations manquantes

invalid_category = {}
response = self.post("users", invalid_category)
response = self.post("categories", invalid_category)
self.expect(response.status_code).to.be.equal_to(400)
self.expect(response.json()).to.have.an_item("code").that._is.equal_to(
"InvalidResource"
Expand All @@ -80,7 +80,7 @@ def test_category_create(self):
# Informations non valides

invalid_category = {"name": ""}
response = self.post("users", invalid_category)
response = self.post("categories", invalid_category)
self.expect(response.status_code).to.be.equal_to(400)
self.expect(response.json()).to.have.an_item("code").that._is.equal_to(
"InvalidResource"
Expand Down
172 changes: 172 additions & 0 deletions .tests/tests/pricing_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
from utils.test_base import TestBase
from utils.auth import BearerAuth
from .audit_tests_helpers import AuditTestHelpers


class PricingTests(TestBase):
def setUp(self):
super().setUp()
self.set_authentication(BearerAuth("09876543210987654321"))
self.audit = AuditTestHelpers(self, 1, 3)

def tearDown(self):
self.unset_authentication()

def test_price_list_get_all(self):
response = self.get("price-lists")
self.expect(response.status_code).to.be.equal_to(200)

price_lists = response.json()
self.expect(price_lists).to.be.a(list)._and._not.empty()

price_list = price_lists[0]
self.expect(price_list).to.have.an_item("id").of.type(int)
self.expect(price_list).to.have.an_item("longName").of.type(str)
self.expect(price_list).to.have.an_item("shortName").of.type(str)
self.expect(price_list).to.have.an_item("requiresMembership").of.type(bool)

def test_price_list_get_one(self):
existing_id = self.get("price-lists").json()[0]["id"]
invalid_id = 12345

# Test avec un tarif existant

response = self.get(f"price-lists/{existing_id}")
self.expect(response.status_code).to.be.equal_to(200)

price_list = response.json()
self.expect(price_list).to.be.a(dict)
self.expect(price_list).to.have.an_item("id").of.type(int)
self.expect(price_list).to.have.an_item("longName").of.type(str)
self.expect(price_list).to.have.an_item("shortName").of.type(str)
self.expect(price_list).to.have.an_item("requiresMembership").of.type(bool)

# Test avec un tarif inexistant

response = self.get(f"price-lists/{invalid_id}")
self.expect(response.status_code).to.be.equal_to(404)

# A faire quand on gèrera les évènements

# def test_price_list_create(self):
# previous_price_list_count = len(self.get("price-lists").json())

# valid_price_list = {
# "longName": "Tarif spécial EtiSmash",
# "shortName": "EtiSmash",
# "requiresMembership": False,
# # ajouter le champ "applicableDuring" ici ?
# }

# with self.audit.watch():
# response = self.post("price-lists", valid_price_list)
# self.expect(response.status_code).to.be.equal_to(201)
# location = self.expect(response.headers).to.have.an_item("Location").value

# created_price_list = response.json()
# self.expect(created_price_list).to.have.an_item("id")
# self.expect(created_price_list["name"]).to.be.equal_to("Jus")

# response = self.get(location)
# self.expect(response.status_code).to.be.equal_to(200)
# created_price_list = response.json()
# self.expect(created_price_list["name"]).to.be.equal_to("Jus")

# new_price_list_count = len(self.get("price-lists").json())
# self.expect(new_price_list_count).to.be.equal_to(previous_price_list_count + 1)

# self.audit.expect_entries(self.audit.price_list_added_action("Jus", "eb069420"))

# for invalid_price_list in INVALID_PRICE_LISTS:
# response = self.post("price-lists", invalid_price_list)
# self.expect(response.status_code).to.be.equal_to(400)
# self.expect(response.json()).to.have.an_item("code").that._is.equal_to(
# "InvalidResource"
# )

def test_price_list_edit(self):
valid_price_list = self.get("price-lists").json()[-1]
valid_price_list.update(shortName="TEST")
price_list_id = valid_price_list["id"]

with self.audit.watch():
response = self.put(f"price-lists/{price_list_id}", valid_price_list)
self.expect(response.status_code).to.be.equal_to(200)

edited_price_list = self.get(f"price-lists/{price_list_id}").json()
self.expect(edited_price_list["shortName"]).to.be.equal_to("TEST")

self.audit.expect_entries(
self.audit.entry(
"PriceListModified", id=price_list_id, name="Tarif test adhérent"
)
)

# Tarif qui n'existe pas

response = self.put("price-lists/12345", valid_price_list)
self.expect(response.status_code).to.be.equal_to(404)

# Informations manquantes

invalid_price_list = {}
response = self.put(f"price-lists/{price_list_id}", invalid_price_list)
self.expect(response.status_code).to.be.equal_to(400)
self.expect(response.json()).to.have.an_item("code").that._is.equal_to(
"InvalidResource"
)

# Informations non valides

invalid_price_list = {"shortName": "long comme un lundi"}
response = self.put(f"price-lists/{price_list_id}", invalid_price_list)
self.expect(response.status_code).to.be.equal_to(400)
self.expect(response.json()).to.have.an_item("code").that._is.equal_to(
"InvalidResource"
)

# Pareil que pour test_price_list_create

# def test_price_list_delete(self):
# price_list = {"name": "Jus"}
# location = self.post("price-lists", price_list).headers["Location"]

# # On supprimme la catégorie

# with self.audit.watch():
# response = self.delete(location)
# self.expect(response.status_code).to.be.equal_to(200)

# self.audit.expect_entries(
# self.audit.price_list_deleted_action("Jus", "eb069420")
# )

# # La catégorie n'existe plus

# response = self.get(location)
# self.expect(response.status_code).to.be.equal_to(404)

# # On ne peut plus le supprimer

# response = self.delete(location)
# self.expect(response.status_code).to.be.equal_to(404)

def test_price_list_no_authentification(self):
self.unset_authentication()

response = self.get("price-lists")
self.expect(response.status_code).to.be.equal_to(401)
response = self.get("price-lists/1")
self.expect(response.status_code).to.be.equal_to(401)
response = self.put("price-lists/1", {})
self.expect(response.status_code).to.be.equal_to(401)

def test_price_list_no_permission(self):
self.set_authentication(BearerAuth("12345678901234567890"))

response = self.get("price-lists")
self.expect(response.status_code).to.be.equal_to(403)
response = self.get("price-lists/1")
self.expect(response.status_code).to.be.equal_to(403)
response = self.put("price-lists/1", {})
self.expect(response.status_code).to.be.equal_to(403)
17 changes: 2 additions & 15 deletions .tests/utils/expectations.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,11 @@ def __init__(self, test_case: TestCase, value):
self.nullable = False

def __check_measurable(self):
if not (
isinstance(self.value, str)
or isinstance(self.value, list)
or isinstance(self.value, tuple)
or isinstance(self.value, dict)
or isinstance(self.value, set)
or hasattr(self.value, "__len__")
):
if not hasattr(self.value, "__len__"):
raise ValueError(f"Values of type {type(self.value)} have no length")

def __check_collection(self):
if not (
isinstance(self.value, dict)
or isinstance(self.value, list)
or isinstance(self.value, tuple)
or isinstance(self.value, set)
or hasattr(self.value, "__getitem__")
):
if not hasattr(self.value, "__getitem__"):
raise ValueError(f"{type(self.value)} is not a collection type")

# ASSERTIONS
Expand Down
2 changes: 1 addition & 1 deletion Core/Applications/AppAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace GalliumPlus.Core.Applications;
/// </summary>
public class AppAccess
{
[Key]
[PrimaryKey]
private readonly int id;
private readonly OneTimeSecret secret;

Expand Down
Loading