-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(backend): add login and register functionality (#267)
Co-authored-by: CEYDANUR ŞEN <128148248+ceydanursen@users.noreply.github.com> Co-authored-by: Yunus Kağan Aydın <133023181+yunuskaydin@users.noreply.github.com> Co-authored-by: yunuskaydin <yunuskaganaydin@gmail.com> Co-authored-by: Mücahit Erdoğan Ünlü <94074126+MucahitErdoganUnlu@users.noreply.github.com> Co-authored-by: Ozan Karakaya <ozank018@gmail.com> Co-authored-by: MucahitErdoganUnlu <mucahit.719@hotmail.com> Co-authored-by: Ümit Can Evleksiz <68506701+umitcan07@users.noreply.github.com> Co-authored-by: Ümit Can Evleksiz <evleksizumitcan@gmail.com>
- Loading branch information
1 parent
37d36aa
commit cd8edf8
Showing
31 changed files
with
551 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
DB_NAME=<database_name> | ||
MYSQL_USER=<mysql_username> | ||
MYSQL_PASSWORD=<mysql_password> | ||
DB_HOST=<IP_address> | ||
DB_PORT=<port_number> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# base image | ||
FROM python:3.12-slim-bullseye | ||
# setup environment variable | ||
ENV DockerHOME=/home/app/webapp | ||
|
||
# set work directory | ||
RUN mkdir -p $DockerHOME | ||
|
||
# where your code lives | ||
WORKDIR $DockerHOME | ||
|
||
# set environment variables | ||
ENV PYTHONDONTWRITEBYTECODE 1 | ||
ENV PYTHONUNBUFFERED 1 | ||
|
||
# install dependencies for mysqlclient | ||
RUN apt-get update && apt-get install -y pkg-config python3-dev default-libmysqlclient-dev build-essential | ||
|
||
# install dependencies | ||
RUN pip install --upgrade pip | ||
|
||
# copy whole project to your docker home directory. | ||
COPY . $DockerHOME | ||
# run this command to install all dependencies | ||
RUN pip install --no-cache-dir -r requirements.txt | ||
# port where the Django app runs | ||
EXPOSE 8000 | ||
# start server | ||
CMD python manage.py runserver |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
# Backend Development | ||
|
||
See the [Full Version](https://github.com/bounswe/bounswe2024group11/wiki/How-to-Prepare-Your-Local-PC-for-the-Backend-Development/_edit) on Wiki | ||
|
||
## How to Run with Docker | ||
|
||
### Prerequisites | ||
|
||
- Docker | ||
|
||
### Steps | ||
|
||
- 1. Clone the repository | ||
|
||
```bash | ||
git clone | ||
``` | ||
|
||
- 2. Change directory to the project's backend directory | ||
|
||
```bash | ||
cd ./bounswe2024group11/backend | ||
``` | ||
|
||
- 3. Create a `.env` file in the `./backend` directory and add the following environment variables | ||
|
||
```bash | ||
cp .env.example .env | ||
``` | ||
|
||
- 4. Enter the values for the environment variables in the `.env` file. | ||
|
||
You can take the credentials for the deployment from the Whatsapp group. | ||
Or you can use local credentials for development purposes. | ||
|
||
- 4.b (Optional) If you want to use local credentials, migrate the database | ||
|
||
Run your MySQL server. | ||
|
||
Then run the following commands to migrate the database | ||
|
||
```bash | ||
python manage.py makemigrations | ||
python manage.py migrate | ||
``` | ||
|
||
- 5. Install Docker and Docker Compose | ||
|
||
- [Docker](https://docs.docker.com/get-docker/) | ||
- [Docker Compose](https://docs.docker.com/compose/install/) | ||
|
||
- 6. Run the following command to start the backend server | ||
|
||
```bash | ||
docker-compose up | ||
``` | ||
|
||
## How to Run Manually | ||
|
||
We need to create a virtual environment and do all backend-related jobs inside that virtual environment. | ||
|
||
```bash | ||
# Change directory to the project's backend directory | ||
cd ./bounswe2024group11/backend | ||
|
||
# create a virtual environment | ||
|
||
## On bash/zsh shells (i.e., on macOS and the most of the Linux-based distros) | ||
python3 -m venv venv | ||
|
||
## On Windows | ||
python -m venv venv | ||
|
||
# Activate the virtual environment | ||
|
||
## On bash/zsh shells (i.e., on macOS and the most of the Linux-based distros) | ||
source ./venv/bin/activate | ||
|
||
## On Windows | ||
venv\Scripts\Activate.ps1 (Powershell) | ||
venv\Scripts\activate.bat (cmd) | ||
``` | ||
|
||
While initializing our project, we decided to use Python 3.12. So create your virtual environments accordingly. | ||
You may want to take a look at [Python Documentation](https://docs.python.org/3/library/venv.html). | ||
|
||
### Installations | ||
|
||
Before starting development, we need to install all the requirements. Inside the `./backend` directory: | ||
|
||
```bash | ||
# Install requirements | ||
pip install -r requirements.txt | ||
``` | ||
|
||
Alternatively, you can install them manually. However, **the list of required libraries may and probably will change** from time to time. So, at the very beginning of the project, you can use these commands, but be careful when you want to use them later. | ||
|
||
```bash | ||
# Install Django | ||
pip install Django | ||
|
||
# Install Django REST Framework | ||
pip install djangorestframework | ||
``` | ||
|
||
### Run the app | ||
|
||
To check if everything is okay, try to run the Django project. Inside the `./backend` directory: | ||
|
||
```bash | ||
# Run the Django project server | ||
python manage.py runserver | ||
``` | ||
|
||
If you see a page without an error when you visit the URL in the terminal, which is similar to `http://127.0.0.1:8000`, your server works properly. | ||
|
||
Congratulations! You have cloned the project, created a virtual environment, and installed the dependencies. Now, you are ready to start your development. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from rest_framework import serializers | ||
from user.models import User | ||
|
||
class UserSerializer(serializers.ModelSerializer): | ||
class Meta(object): | ||
model = User | ||
fields = '__all__' |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from rest_framework.test import APITestCase | ||
from django.urls import reverse | ||
from faker import Faker | ||
|
||
class TestSetUp(APITestCase): | ||
def setUp(self): | ||
self.register_url = reverse('signup') | ||
self.login_url = reverse('login') | ||
|
||
|
||
self.user_data1 = { | ||
'username': Faker().user_name(), | ||
'email': Faker().email(), | ||
'password': Faker().password(), | ||
} | ||
|
||
self.user_data2 = { | ||
'username': Faker().user_name(), | ||
'email': Faker().email(), | ||
'password': Faker().password(), | ||
} | ||
|
||
return super().setUp() | ||
|
||
def tearDown(self): | ||
return super().tearDown() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from .test_setup import TestSetUp | ||
from django.urls import reverse | ||
from faker import Faker | ||
|
||
class TestView(TestSetUp): | ||
|
||
def test_register_user(self): | ||
response = self.client.post(self.register_url, self.user_data1, format='json') | ||
print(response.data) | ||
self.assertEqual(response.status_code, 201) | ||
self.assertEqual(response.data['user']['username'], self.user_data1['username']) | ||
self.assertEqual(response.data['user']['email'], self.user_data1['email']) | ||
self.assertTrue('token' in response.data) | ||
|
||
def test_register_nonunique_username(self): | ||
response = self.client.post(self.register_url, self.user_data1, format='json') | ||
response = self.client.post(self.register_url, self.user_data1, format='json') | ||
print(response.data) | ||
self.assertEqual(response.status_code, 400) | ||
self.assertEqual(response.data['username'][0], 'user with this username already exists.') | ||
|
||
def test_false_login_user(self): | ||
response = self.client.post(self.login_url, self.user_data1, format='json') | ||
print(response.data) | ||
self.assertEqual(response.status_code, 401) | ||
|
||
def test_login_user(self): | ||
self.client.post(self.register_url, self.user_data1, format='json') | ||
response = self.client.post(self.login_url, self.user_data1, format='json') | ||
print(response.data) | ||
self.assertEqual(response.status_code, 200) | ||
self.assertEqual(response.data['user']['username'], self.user_data1['username']) | ||
self.assertEqual(response.data['user']['email'], self.user_data1['email']) | ||
self.assertTrue('token' in response.data) | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from django.urls import path | ||
from . import views | ||
|
||
urlpatterns = [ | ||
# path('test_token', views.test_token, name="test_token"), | ||
path('signup', views.register, name="signup"), | ||
path('login', views.login, name="login"), | ||
|
||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from rest_framework.response import Response | ||
from rest_framework.decorators import api_view | ||
from user.models import User | ||
from .serializer import UserSerializer | ||
from rest_framework import status | ||
from rest_framework.authtoken.models import Token | ||
from django.shortcuts import get_object_or_404 | ||
|
||
@api_view(['POST']) | ||
def register(request): | ||
required_fields = ['username', 'password', 'email'] | ||
if not all([field in request.data for field in required_fields]): | ||
return Response({"res":"Please provide all required fields."}, status=status.HTTP_400_BAD_REQUEST) | ||
|
||
serializer = UserSerializer(data=request.data) | ||
if serializer.is_valid(): | ||
serializer.save() | ||
user = User.objects.get(username=request.data['username']) | ||
user.set_password(request.data['password']) | ||
user.save() | ||
token = Token.objects.create(user=user) | ||
return Response({"token": token.key, "user": serializer.data}, status=status.HTTP_201_CREATED) | ||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) | ||
|
||
@api_view(['POST']) | ||
def login(request): | ||
required_fields = ['username', 'password'] | ||
if not all([field in request.data for field in required_fields]): | ||
return Response({"res":"Please provide both username and password."}, status=status.HTTP_400_BAD_REQUEST) | ||
|
||
try: | ||
user = User.objects.get(username=request.data['username']) | ||
except User.DoesNotExist: | ||
return Response({"res": "Username not found."}, status=status.HTTP_401_UNAUTHORIZED) | ||
|
||
if not user.check_password(request.data['password']): | ||
return Response({"res":"password does not match."}, status=status.HTTP_401_UNAUTHORIZED) | ||
token, created = Token.objects.get_or_create(user=user) | ||
serializer = UserSerializer(instance=user) | ||
return Response({"token": token.key, "user": serializer.data}, status=status.HTTP_200_OK) | ||
|
||
|
||
#@api_view(['GET']) | ||
#def test_token(request): | ||
# return Response({"res":"Token is valid!"}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,4 +19,5 @@ | |
|
||
urlpatterns = [ | ||
path('admin/', admin.site.urls), | ||
path('user/', include('api.urls')), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# version is deprecated after docker 25.X | ||
# version: '3.7' | ||
|
||
|
||
services: | ||
app: | ||
build: | ||
context: . | ||
ports: | ||
- "8000:8000" | ||
volumes: | ||
- .:/home/app/webapp | ||
command: > | ||
sh -c "python manage.py makemigrations && | ||
python manage.py migrate && | ||
python manage.py runserver 0.0.0.0:8000" | ||
env_file: .env | ||
restart: "on-failure" |
Binary file not shown.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.contrib import admin | ||
|
||
from .models import User | ||
# Register your models here. | ||
|
||
admin.site.register(User) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class UserConfig(AppConfig): | ||
default_auto_field = 'django.db.models.BigAutoField' | ||
name = 'user' |
Oops, something went wrong.