Skip to content

account and tracker projects #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
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
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Django #
*.log
*.pot
*.pyc
__pycache__
db.sqlite3
media


# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# CryptoTracker project description
We implement a crypto tracker project using djano rest framework.

Check List of requested features:
- [x] User able to signup (name, username, password and KuCoin information:{api_key, secret_key and passphrase})
- [x] User able to sign in (using django rest token authentication)
- [x] User able to request position tracking and cancel it. (using **APScheduler** library every 30 secs fetch user's positions)
- [x] User able to see list of open position
- [x] Application track user's positions (if user requested for it) every 30 secs
- [x] Application stores users that requested for positions tracking and track their positions in a interval (Handeling muti users)
- [x] Application start position tracking by starting application (resume traking with restarting application)

Also you can see the API documentation created using postman in the link below:

[CryptoTracker API documentation](https://documenter.getpostman.com/view/2983315/UzR1L3Ai)



# In name of Allah

## Introduction
Expand Down
Empty file.
6 changes: 6 additions & 0 deletions cryptoTracker/accounts/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.contrib import admin
from .models import CustomUser
# Register your models here.

admin.site.register(CustomUser)

7 changes: 7 additions & 0 deletions cryptoTracker/accounts/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.apps import AppConfig


class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'

37 changes: 37 additions & 0 deletions cryptoTracker/accounts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 4.0.6 on 2022-07-17 13:58

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='CustomUser',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('name', models.CharField(max_length=100)),
('username', models.CharField(max_length=100)),
('api_key', models.CharField(max_length=200)),
('secret_key', models.CharField(max_length=200)),
('api_passphrase', models.CharField(max_length=200)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Profile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Generated by Django 4.0.6 on 2022-07-20 08:22

import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.utils.timezone
import fernet_fields.fields


class Migration(migrations.Migration):

dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('accounts', '0001_initial'),
]

operations = [
migrations.DeleteModel(
name='Profile',
),
migrations.AlterModelOptions(
name='customuser',
options={'verbose_name': 'user', 'verbose_name_plural': 'users'},
),
migrations.AlterModelManagers(
name='customuser',
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.AddField(
model_name='customuser',
name='date_joined',
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined'),
),
migrations.AddField(
model_name='customuser',
name='email',
field=models.EmailField(blank=True, max_length=254, verbose_name='email address'),
),
migrations.AddField(
model_name='customuser',
name='first_name',
field=models.CharField(blank=True, max_length=150, verbose_name='first name'),
),
migrations.AddField(
model_name='customuser',
name='groups',
field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups'),
),
migrations.AddField(
model_name='customuser',
name='is_active',
field=models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active'),
),
migrations.AddField(
model_name='customuser',
name='is_staff',
field=models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status'),
),
migrations.AddField(
model_name='customuser',
name='is_superuser',
field=models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status'),
),
migrations.AddField(
model_name='customuser',
name='last_name',
field=models.CharField(blank=True, max_length=150, verbose_name='last name'),
),
migrations.AddField(
model_name='customuser',
name='user_permissions',
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions'),
),
migrations.AlterField(
model_name='customuser',
name='api_key',
field=fernet_fields.fields.EncryptedCharField(max_length=200),
),
migrations.AlterField(
model_name='customuser',
name='api_passphrase',
field=fernet_fields.fields.EncryptedCharField(max_length=200),
),
migrations.AlterField(
model_name='customuser',
name='secret_key',
field=fernet_fields.fields.EncryptedCharField(max_length=200),
),
migrations.AlterField(
model_name='customuser',
name='username',
field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username'),
),
]
40 changes: 40 additions & 0 deletions cryptoTracker/accounts/migrations/0003_order_activetrackinguser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 4.0.6 on 2022-07-21 09:21

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('accounts', '0002_delete_profile_alter_customuser_options_and_more'),
]

operations = [
migrations.CreateModel(
name='Order',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('order_id', models.CharField(max_length=100)),
('symbol', models.CharField(max_length=50)),
('opType', models.CharField(max_length=20)),
('type', models.CharField(max_length=20)),
('side', models.CharField(max_length=20)),
('price', models.CharField(max_length=20)),
('size', models.CharField(max_length=20)),
('fee', models.CharField(max_length=20)),
('isActive', models.CharField(max_length=20)),
('order_createdAt', models.IntegerField()),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='ActiveTrackingUser',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('track', models.BooleanField(default=False)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.0.6 on 2022-07-21 12:03

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('accounts', '0003_order_activetrackinguser'),
]

operations = [
migrations.RemoveField(
model_name='order',
name='user',
),
migrations.DeleteModel(
name='ActiveTrackingUser',
),
migrations.DeleteModel(
name='Order',
),
]
Empty file.
14 changes: 14 additions & 0 deletions cryptoTracker/accounts/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from symtable import Symbol
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, AbstractUser
from cryptography.fernet import Fernet
from django.conf import settings
from fernet_fields import EncryptedCharField
from django.contrib.auth.models import UserManager

class CustomUser(AbstractUser):
name = models.CharField(max_length=100)
api_key = EncryptedCharField(max_length=200)
secret_key = EncryptedCharField(max_length=200)
api_passphrase = EncryptedCharField(max_length=200)

29 changes: 29 additions & 0 deletions cryptoTracker/accounts/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from rest_framework import serializers
from .models import CustomUser
from rest_framework.validators import UniqueValidator


class RegisterSerializer(serializers.Serializer):
name = serializers.CharField(required=True, write_only=True)
username = serializers.CharField(
required=True, write_only=True,
validators=[UniqueValidator(queryset=CustomUser.objects.all(), message='a user is already registered with this username!')]
)
api_key = serializers.CharField(required=True, write_only=True)
secret_key = serializers.CharField(required=True, write_only=True)
api_passphrase = serializers.CharField(required=True, write_only=True)
password = serializers.CharField(required=True, write_only=True, style={"input_type": "password"})

def create(self, validated_data):
user = CustomUser.objects.create(**validated_data)
user.set_password(validated_data['password'])
user.save()
return user

class LoginSerializer(serializers.Serializer):
username = serializers.CharField(required=True, write_only=True)
password = serializers.CharField(required=True, write_only=True, style={"input_type": "password"})

def validate(self, attrs):
return super().validate(attrs)

3 changes: 3 additions & 0 deletions cryptoTracker/accounts/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
14 changes: 14 additions & 0 deletions cryptoTracker/accounts/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.urls import path
from .views import (
RegisterAPIView,
LogoutAPIView
)
from rest_framework.authtoken.views import obtain_auth_token


urlpatterns = [
path('register/', RegisterAPIView.as_view()),
path('login/', view=obtain_auth_token),
path('logout/', LogoutAPIView.as_view()),

]
24 changes: 24 additions & 0 deletions cryptoTracker/accounts/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from rest_framework.generics import (
CreateAPIView,
)
from .models import CustomUser
from .serializers import RegisterSerializer
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class RegisterAPIView(CreateAPIView):
serializer_class = RegisterSerializer
permission_classes = (AllowAny,)
queryset = CustomUser.objects.all()


class LogoutAPIView(APIView):
permission_classes = (IsAuthenticated, )

def post(self, request):
request.user.auth_token.delete()
return Response(data={'message': f" {request.user.username} logged out"}, status=status.HTTP_200_OK)

3 changes: 3 additions & 0 deletions cryptoTracker/cryptoTracker/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import pymysql

pymysql.install_as_MySQLdb()
16 changes: 16 additions & 0 deletions cryptoTracker/cryptoTracker/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
ASGI config for cryptoTracker project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cryptoTracker.settings')

application = get_asgi_application()
Loading