diff --git a/Mapapi/migrations/0006_discussionmessage.py b/Mapapi/migrations/0006_discussionmessage.py
new file mode 100644
index 00000000..481b0afc
--- /dev/null
+++ b/Mapapi/migrations/0006_discussionmessage.py
@@ -0,0 +1,26 @@
+# Generated by Django 4.2.7 on 2025-02-27 17:27
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('Mapapi', '0005_user_is_verified_user_otp_user_otp_expiration_and_more'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='DiscussionMessage',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('message', models.TextField()),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('collaboration', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Mapapi.collaboration')),
+ ('incident', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Mapapi.incident')),
+ ('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/Mapapi/migrations/0008_discussionmessage_recipient.py b/Mapapi/migrations/0008_discussionmessage_recipient.py
new file mode 100644
index 00000000..cb61ac8c
--- /dev/null
+++ b/Mapapi/migrations/0008_discussionmessage_recipient.py
@@ -0,0 +1,20 @@
+# Generated by Django 4.2.7 on 2025-03-03 11:21
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('Mapapi', '0006_discussionmessage'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='discussionmessage',
+ name='recipient',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='received_messages', to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/Mapapi/migrations/0009_alter_collaboration_unique_together.py b/Mapapi/migrations/0009_alter_collaboration_unique_together.py
new file mode 100644
index 00000000..2409d48b
--- /dev/null
+++ b/Mapapi/migrations/0009_alter_collaboration_unique_together.py
@@ -0,0 +1,17 @@
+# Generated by Django 4.2.7 on 2025-03-03 11:43
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('Mapapi', '0008_discussionmessage_recipient'),
+ ]
+
+ operations = [
+ migrations.AlterUniqueTogether(
+ name='collaboration',
+ unique_together={('incident', 'user')},
+ ),
+ ]
diff --git a/Mapapi/models.py b/Mapapi/models.py
index cd6eda61..591619a0 100644
--- a/Mapapi/models.py
+++ b/Mapapi/models.py
@@ -165,7 +165,7 @@ def generate_otp(self):
self.save()
def send_verification_email(self):
- verification_link = f"mapactionapp://verify-email/{self.verification_token}"
+ verification_link = f"com.uwaish.MapActionApp://verify-email/{self.verification_token}"
context = {"verification_link": verification_link}
subject = "Vérification de votre compte"
template_name = "emails/verification_email.html"
@@ -390,6 +390,8 @@ class Collaboration(models.Model):
other_option = models.CharField(max_length=255, blank=True, null=True)
status = models.CharField(max_length=20, default='pending')
+ class Meta:
+ unique_together = (("incident", "user"),)
def __str__(self):
return f"Collaboration on {self.incident} by {self.user}"
@@ -446,3 +448,14 @@ class UserAction(models.Model):
def __str__(self):
return self.action
+
+class DiscussionMessage(models.Model):
+ incident = models.ForeignKey('Incident', on_delete=models.CASCADE)
+ collaboration = models.ForeignKey(Collaboration, on_delete=models.CASCADE)
+ sender = models.ForeignKey(User, on_delete=models.CASCADE)
+ message = models.TextField()
+ created_at = models.DateTimeField(auto_now_add=True)
+ recipient = models.ForeignKey(User, on_delete=models.CASCADE, related_name="received_messages", null=True, blank=True)
+
+ def __str__(self):
+ return f"Message de {self.sender} le {self.created_at}"
diff --git a/Mapapi/serializer.py b/Mapapi/serializer.py
index 0c86335e..d4a0c811 100644
--- a/Mapapi/serializer.py
+++ b/Mapapi/serializer.py
@@ -275,3 +275,13 @@ class Meta:
model = UserAction
fields = '__all__'
+
+class DiscussionMessageSerializer(serializers.ModelSerializer):
+ sender = UserSerializer(read_only=True)
+ recipient = UserSerializer(read_only=True)
+ class Meta:
+ model = DiscussionMessage
+ fields = ['id', 'incident', 'collaboration', 'sender', 'message', 'created_at','recipient']
+ read_only_fields = ('sender', 'incident', 'collaboration','recipient')
+
+
diff --git a/Mapapi/urls.py b/Mapapi/urls.py
index f70514f2..5484b513 100644
--- a/Mapapi/urls.py
+++ b/Mapapi/urls.py
@@ -102,6 +102,8 @@
path('collaborations/accept/', AcceptCollaborationView.as_view(), name='accept-collaboration'),
path('collaboration/', CollaborationView.as_view(), name="collaboration"),
path('collaboration///', HandleCollaborationRequestView.as_view(), name="handle_collaboration_request"),
+ path('discussion//', DiscussionMessageView.as_view(), name='discussion'),
+
# Search Incident
path('Search/', IncidentSearchView.as_view(), name="search"),
path('prediction/', PredictionView.as_view(), name="predicton"),
diff --git a/Mapapi/views.py b/Mapapi/views.py
index a7c7b3e8..337d471e 100644
--- a/Mapapi/views.py
+++ b/Mapapi/views.py
@@ -1967,10 +1967,16 @@ def send_sms(phone_number, otp_code):
class CollaborationView(generics.CreateAPIView, generics.ListAPIView):
- permission_classes = ()
+ permission_classes = [IsAuthenticated]
queryset = Collaboration.objects.all()
serializer_class = CollaborationSerializer
+ def get_queryset(self):
+ user = self.request.user
+ return Collaboration.objects.filter(
+ Q(user=user) | Q(incident__taken_by=user)
+ )
+
def post(self, request, *args, **kwargs):
try:
serializer = CollaborationSerializer(data=request.data)
@@ -2402,3 +2408,47 @@ def post(self, request):
return Response({"message": "OTP invalide ou expiré"}, status=status.HTTP_400_BAD_REQUEST)
except User.DoesNotExist:
return Response({"message": "Utilisateur non trouvé"}, status=status.HTTP_404_NOT_FOUND)
+
+
+class DiscussionMessageView(generics.ListCreateAPIView):
+ serializer_class = DiscussionMessageSerializer
+ permission_classes = [IsAuthenticated]
+
+ def get_queryset(self):
+ incident_id = self.kwargs.get('incident_id')
+ user = self.request.user
+ try:
+ collaboration = Collaboration.objects.get(
+ Q(user=user) | Q(incident__taken_by=user),
+ incident__id=incident_id,
+ status='accepted'
+ )
+ except Collaboration.DoesNotExist:
+ raise NotFound("Aucune discussion trouvée pour cet incident.")
+
+
+ return DiscussionMessage.objects.filter(
+ incident__id=incident_id
+ ).filter(
+ Q(sender=user) | Q(recipient=user)
+ )
+
+ def perform_create(self, serializer):
+ incident_id = self.kwargs.get('incident_id')
+ try:
+ collaboration = Collaboration.objects.get(incident__id=incident_id, user=self.request.user, status='accepted')
+ recipient = collaboration.incident.taken_by
+ except Collaboration.DoesNotExist:
+ collaboration = Collaboration.objects.get(incident__id=incident_id, status='accepted')
+ recipient = collaboration.user
+
+ if collaboration.incident.etat == "resolved":
+ raise ValidationError("Cet incident est résolu, la discussion est terminée.")
+
+ serializer.save(
+ sender=self.request.user,
+ incident=collaboration.incident,
+ collaboration=collaboration,
+ recipient=recipient
+ )
+
diff --git a/README.md b/README.md
index 482e68cb..291c4b23 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
-
+
Mapapi
- Comprehensive solution for managing and visualizing environment-related incidents.
+ Comprehensive backend solution for managing and visualizing environment-related incidents via the Map Action platform.
@@ -31,96 +31,194 @@
## Table of Contents
- [Overview](#overview)
-- [Technologies](#technologies)
-- [Features](#features)
+- [Technologies Used](#technologies-used)
+- [Core Features](#core-features)
- [System Architecture](#system-architecture)
-- [Setup](#setup)
-- [Contribute to the project](#contribute-to-the-project)
-- [Authors](#authors)
-- [Licensing](#licensing)
-- [Developer Documentation](#developer-documentation)
-- [DPG Assessment](#dpg-assessment)
+- [Local Development Environment Setup](#local-development-environment-setup)
+ - [Prerequisites](#prerequisites)
+ - [Step 1: Clone the Repository](#step-1-clone-the-repository)
+ - [Step 2: Configure Environment Variables](#step-2-configure-environment-variables)
+ - [Step 3: Build and Run the Application Services](#step-3-build-and-run-the-application-services)
+ - [Step 4: Access the Running Application](#step-4-access-the-running-application)
+ - [Step 5: Verify the Setup (Recommended)](#step-5-verify-the-setup-recommended)
+ - [Step 6: Stopping the Application](#step-6-stopping-the-application)
+ - [Running Management Commands](#running-management-commands)
+- [How to Contribute](#how-to-contribute)
+- [Project Authors](#project-authors)
+- [Licensing Information](#licensing-information)
+- [Developer Documentation Link](#developer-documentation-link)
+- [Digital Public Goods Assessment](#digital-public-goods-assessment)
## Overview
-Mapapi (Map Action API) is a comprehensive solution that combines a robust API. This project is designed to manage and visualize environment-related incidents efficiently and effectively.
+Mapapi (Map Action API) serves as the backend API for the Map Action platform. It provides a robust and scalable solution for managing, storing, and retrieving data related to environment-related incidents reported via the associated mobile app and dashboard.
-## Technologies
+## Technologies Used
-- **Django**: Used to build the backend for Map Action mobile app and dashboard.
-- **Postgres**: Used to store users data and incidents reported
-- **Celery**: Used as an asynchronous task queue/job
-- **Redis**: Used as a message broker for Celery and for caching.
+- **Django**: High-level Python web framework used for building the core RESTful API.
+- **PostgreSQL**: Powerful, open-source object-relational database system used for persistent data storage (users, incidents, etc.).
+- **Celery**: Distributed task queue system for handling background processes asynchronously, ensuring the API remains responsive.
+- **Redis**: In-memory data structure store, primarily used as a fast message broker for Celery task queues and potentially for caching.
+- **Docker & Docker Compose**: Containerization technology used to package the application and its dependencies, ensuring consistent development, testing, and deployment environments.
+- **Nginx**: High-performance web server often used as a reverse proxy and load balancer (acting as the entry point in the local setup).
+- **Daphne**: ASGI server used to run the Django application, enabling handling of asynchronous requests.
-## Features
+## Core Features
-- **API**: Provides endpoints for managing and retrieving data on environment-related incidents.
-- **Asynchronous Task Processing**: Uses Celery and Redis to handle background tasks efficiently.
-- **Database Management**: Utilizes Postgres for robust data storage and querying capabilities.
+- **Incident Management API**: Provides RESTful endpoints for CRUD (Create, Read, Update, Delete) operations on environmental incident data.
+- **User Authentication & Authorization**: Manages user accounts, registration, login, and permissions.
+- **Asynchronous Task Processing**: Offloads tasks like sending notifications or processing media uploads to Celery workers.
+- **Geospatial Data Capabilities**: Implied functionality for handling location data associated with incidents.
## System Architecture

+*This diagram shows the flow of requests and the interaction between the various components like Nginx, the Django API (api-server), PostgreSQL database, Redis, and Celery workers.*
-### Setup
+## Local Development Environment Setup
-#### Prerequisites
+Follow these steps carefully to configure and run the Mapapi project on your local machine using Docker for development and testing purposes.
-- Ensure you have Docker and Docker Compose installed on your system.
+### Prerequisites
-#### Clone the repository
+Before you start, ensure you have the following essential tools installed on your system:
+
+- **Docker Engine:** The core engine for creating and running containers. Download and install it from the official Docker website: [Install Docker Engine](https://docs.docker.com/engine/install/)
+- **Docker Compose:** The tool used to define and manage multi-container applications based on YAML configuration files. Docker Compose V2 is typically included with Docker Desktop installations. Verify your installation: [Install Docker Compose](https://docs.docker.com/compose/install/)
+
+### Step 1: Clone the Repository
+
+Get a local copy of the project's source code.
```bash
+# Clone the original repository from GitHub
git clone https://github.com/223MapAction/Mapapi.git
+
+# Navigate into the newly created project directory
cd Mapapi
```
-#### Build and run the containers
+**Note:** If you first *forked* the repository to your own GitHub account (perhaps under a different name like `Mapapi-Contribution`), clone *your fork* using its specific URL. Then, ensure you `cd` into the correct directory name that was created locally (e.g., `cd Mapapi-Contribution`).
-- Use Docker Compose to build and run the services defined in the `_cd_pipeline.yml` file.
+### Step 2: Configure Environment Variables
-```bash
-docker-compose -f _cd_pipeline.yml up --build
-```
+Mapapi requires specific environment variables for configuration, such as database credentials and secret keys.
-- This command will build the Docker images and start the containers for the application, including the database, API server, Redis, and other services.
+- The project should contain an example file named **`.env.example`** in the root directory. This file lists the necessary variables.
+- Create your own local configuration file by **copying** this example:
-#### Access the application
+ ```bash
+ # Make sure you are in the project's root directory
+ cp .env.example .env
+ ```
+- Open the newly created **`.env`** file in your text editor.
+- Review the variables. While many defaults in `.env.example` might work for local setup, you might need to set specific values (especially for external service keys if you plan to test those features, though they might not be required for basic setup).
+- **Crucially:** The **`.env`** file contains sensitive information and **should NEVER be committed to Git**. It is intentionally included in the `.gitignore` file to prevent accidental commits.
-- Once the containers are up and running, you can access the application at `http://localhost`.
+### Step 3: Build and Run the Application Services
-#### Stopping the services
+Use Docker Compose to build the required Docker images and start all the necessary services (API, database, Redis, Nginx, Celery, etc.).
-- To stop the running services, use:
+- Execute the following command from the project's root directory:
-```bash
-docker-compose -f _cd_pipeline.yml down
-```
+ ```bash
+ # Use the specific compose file provided and build images if needed
+ docker-compose -f _cd_pipeline.yml up --build
+ ```
+
+ * **`docker-compose -f _cd_pipeline.yml`**: Tells Docker Compose to use this specific configuration file.
+ * **`up`**: Starts all the services defined in the file in the foreground, displaying their logs.
+ * **`--build`**: Forces Docker Compose to build the images for services like `api-server` before starting them. This is important on the first run or after changing Dockerfiles or dependencies (like `requirements.txt`). You can omit `--build` on subsequent runs for faster startup if no underlying code/dependencies have changed.
+
+- You will see logs from various containers being created and started. **Keep this terminal window running** – closing it will stop the application services.
+- **Note on Migrations:** The startup command for the `api-server` service in the `_cd_pipeline.yml` file is configured to automatically wait for the database and then apply any necessary Django database migrations (`makemigrations`, `migrate`). You **do not** need to run these migrations manually as a separate step after starting the containers. Check the initial logs from the `api-server` container to confirm migrations ran successfully.
+
+### Step 4: Access the Running Application
+
+Once all containers are up and running (check the logs from the previous step), the application should be accessible through the Nginx gateway.
+
+- Open your preferred web browser.
+- Navigate to: **`http://localhost`** (This uses the default HTTP port 80, which Nginx is configured to listen on in the `_cd_pipeline.yml` file).
+
+- You should see the Django REST Framework's browsable API interface or potentially a landing page served by the application, confirming it's running.
+
+### Step 5: Verify the Setup (Recommended)
-This setup leverages Docker to manage dependencies and services, ensuring a consistent environment across different systems.
+Perform these quick checks in a **new terminal window** (while the services are still running from the `docker-compose up` command in the first terminal) to ensure key components are functioning correctly.
-## Contribute to the project
+- #### Check Container Status:
+ List all running containers managed by the compose file:
+ ```bash
+ docker-compose -f _cd_pipeline.yml ps
+ ```
+ * **Expected Outcome:** You should see multiple services listed (e.g., `api-server`, `postgres-db`, `redis-server`, `celery_worker`, `nginx`, `pgadmin`). Verify their `State` is `Up`.
-Map Action is an open source project. Fell free to fork the source and contribute with your features. Please follow our [contribution guidelines](CONTRIBUTING.md).
+- #### Confirm API Access:
+ Re-check access in your web browser as described in Step 4: `http://localhost`.
+ * **Expected Output:** Successful loading of the API interface or application page.
-## Authors
+- #### Test a Management Command:
+ Execute a simple Django management command *inside* the `api-server` container:
+ ```bash
+ docker-compose -f _cd_pipeline.yml exec api-server python3 manage.py showmigrations
+ ```
+ * **Expected Output:** The command should run without errors and list all the Django apps and the status of their database migrations (most should have `[X]` indicating they are applied).
-Our code squad : A7640S, Yugo19 & immerSIR
+### Step 6: Stopping the Application
-## Licensing
+When you're finished working with the application:
-This project was built under the [GNU Affero General Public License](LICENSE).
+1. Go back to the **first terminal window** where you ran `docker-compose up ...`.
+2. Press **`Ctrl + C`** to stop the running services gracefully.
+3. **(Optional Cleanup):** To stop and *remove* the containers, networks, and volumes created by `up`, you can run:
+ ```bash
+ docker-compose -f _cd_pipeline.yml down
+ ```
-## Developer Documentation
+### Running Management Commands
-For more detailed information, please refer to the [Developer Documentation](https://223mapaction.github.io/Mapapi/).
+To execute other Django `manage.py` commands (like `createsuperuser`, `shell`, `dbshell`, custom commands) while the services are running via `docker-compose up`:
-## DPG Assessment
+1. Open a **new terminal window**.
+2. Navigate to the project's root directory.
+3. Use the `docker-compose exec` command, specifying the `api-server` service:
-For a detailed assessment of the project's compliance with the Digital Public Goods Standard, please see the [DIGITAL PUBLIC GOODS STANDARD ASSESSMENT](DPG_ASSESSMENT.md). This document outlines our alignment with sustainable development goals, open licensing, and more.
+ ```bash
+ docker-compose -f _cd_pipeline.yml exec api-server python3 manage.py
+ ```
+ *Replace `` with the actual command and arguments (e.g., `createsuperuser`, `shell`).*
-##### Note
+---
+
+## How to Contribute
+
+Map Action is an open-source project, and we warmly welcome contributions from the community! Whether it's reporting bugs, proposing new features, improving documentation, or writing code, your help is valued.
+
+Please refer to our detailed [**Contribution Guidelines**](CONTRIBUTING.md) before submitting contributions. This ensures a smooth and effective process for everyone.
+
+Key contribution areas include:
+
+- **Reporting Issues:** Use the GitHub Issues tab to report bugs or suggest enhancements. Check if a similar issue exists first!
+- **Submitting Pull Requests (PRs):** For code or documentation changes, follow the fork/branch/PR workflow described in the guidelines. Ensure your PRs are well-described and reference relevant issues (e.g., `Closes #123`).
+- **Code Reviews:** Help review existing Pull Requests to improve code quality and share knowledge.
+- **Discussions:** Participate in discussions on GitHub Issues or other community channels.
+
+## Project Authors
+
+This project is developed and maintained by our dedicated code squad: A7640S, Yugo19 & immerSIR.
+
+## Licensing Information
+
+Mapapi is licensed under the [**GNU Affero General Public License v3.0 (AGPL-3.0)**](LICENSE). Please review the `LICENSE` file in the repository for the full terms and conditions.
+
+## Developer Documentation Link
+
+For more in-depth technical details, API specifications, and advanced guides, please consult the hosted [**Developer Documentation**](https://223mapaction.github.io/Mapapi/).
+
+## Digital Public Goods Assessment
+
+Mapapi has undergone an assessment against the Digital Public Goods Standard. You can find the detailed report here: [**DPG Assessment**](DPG_ASSESSMENT.md). This document outlines our alignment with principles like open standards, open licensing, and relevance to Sustainable Development Goals (SDGs).
+
+```
-if your system is Linux or MacOS,
-you have to add 3 on python
-example python3 manage.py runserver
+---
\ No newline at end of file
diff --git a/template/emails/verification_email.html b/template/emails/verification_email.html
index 44e50a13..abfda22f 100644
--- a/template/emails/verification_email.html
+++ b/template/emails/verification_email.html
@@ -74,7 +74,7 @@ Bienvenue sur Map Action
Bonjour,
Merci de vous être inscrit sur Map Action ! Veuillez cliquer sur le bouton ci-dessous pour vérifier votre compte et commencer à explorer nos fonctionnalités.
-
Vérifier mon compte
+
Vérifier mon compte
Si vous n'avez pas demandé cette vérification, vous pouvez ignorer ce message.