Skip to content
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

Support multiple wallet for same chains #129

Merged
Merged
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
32 changes: 18 additions & 14 deletions authentication/helpers.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import requests
import base64
import json
import time
import requests
import base64

import ed25519
from eth_account.messages import encode_defunct
from web3 import Web3
from eth_account import Account
import requests
from django.apps import apps
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.apps import apps
from eth_account import Account
from eth_account.messages import encode_defunct


def verify_signature_eth_scheme(address, signature):
def verify_signature_eth_scheme(address, message, signature):
try:
digest = encode_defunct(text=address)
digest = encode_defunct(text=message)
signer = Account.recover_message(digest, signature=signature)
if signer == address:
return True
Expand All @@ -30,10 +29,12 @@ def __init__(self, app) -> None:
self.app = app

def create_verification_link(self, contextId):
return f"https://app.brightid.org/link-verification/http:%2F%2Fnode.brightid.org/{self.app}/{str(contextId).lower()}"
return f"https://app.brightid.org/link-verification/http:%2F\
%2Fnode.brightid.org/{self.app}/{str(contextId).lower()}"

def create_qr_content(self, contextId):
return f"brightid://link-verification/http:%2f%2fnode.brightid.org/{self.app}/{str(contextId).lower()}" # TODO
return f"brightid://link-verification/http:%2f%2fnode.bright\
id.org/{self.app}/{str(contextId).lower()}" # TODO

def get_verification_status(self, context_id, verification):
if verification == "BrightID" or verification == "Meet":
Expand All @@ -44,7 +45,8 @@ def get_verification_status(self, context_id, verification):
raise ValueError("Invalid verification type")

# get list of context ids from brightId
endpoint = f"https://aura-node.brightid.org/brightid/v5/verifications/{self.app}/{context_id}?verification={verification_type}"
endpoint = f"https://aura-node.brightid.org/brightid/v5/veri\
fications/{self.app}/{context_id}?verification={verification_type}"
# print("endpoint: ", endpoint)
bright_response = requests.get(endpoint)
# decode response
Expand Down Expand Up @@ -109,15 +111,17 @@ def is_username_valid_and_available(username):
# Check if the string matches the required format
validator = RegexValidator(
regex=r"^(?=.*[a-zA-Z])([\w.@+-]{3,150})$",
message="Username must be more than 2 characters, contain at least one letter, and only contain letters, digits and @/./+/-/_.",
message="Username must be more than 2 characters, contain at \
least one letter, and only contain letters, digits and @/./+/-/_.",
)

try:
validator(username)
except ValidationError:
return (
False,
"Username must be more than 2 characters, contain at least one letter, and only contain letters, digits and @/./+/-/_.",
"Username must be more than 2 characters, contain at least one \
letter, and only contain letters, digits and @/./+/-/_.",
"validation_error",
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 4.0.4 on 2023-09-27 11:03

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('authentication', '0017_alter_userprofile_username'),
]

operations = [
migrations.AlterUniqueTogether(
name='wallet',
unique_together={('wallet_type', 'address')},
),
migrations.AddField(
model_name='wallet',
name='primary',
field=models.BooleanField(default=False),
),
]
17 changes: 17 additions & 0 deletions authentication/migrations/0019_alter_wallet_unique_together.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.0.4 on 2023-09-28 03:27

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('authentication', '0018_alter_wallet_unique_together_wallet_primary'),
]

operations = [
migrations.AlterUniqueTogether(
name='wallet',
unique_together=set(),
),
]
14 changes: 14 additions & 0 deletions authentication/migrations/0021_merge_20231126_1858.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 4.0.4 on 2023-11-26 18:58

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('authentication', '0019_alter_wallet_unique_together'),
('authentication', '0020_remove_userprofile_is_new_by_wallet'),
]

operations = [
]
17 changes: 17 additions & 0 deletions authentication/migrations/0022_remove_wallet_primary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.0.4 on 2023-11-30 12:02

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('authentication', '0021_merge_20231126_1858'),
]

operations = [
migrations.RemoveField(
model_name='wallet',
name='primary',
),
]
18 changes: 18 additions & 0 deletions authentication/migrations/0023_wallet_created_at.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.0.4 on 2023-11-30 15:49

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('authentication', '0022_remove_wallet_primary'),
]

operations = [
migrations.AddField(
model_name='wallet',
name='created_at',
field=models.DateTimeField(auto_now_add=True, null=True),
),
]
22 changes: 16 additions & 6 deletions authentication/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ def get_or_create(self, first_context_id):
return _profile


# class WalletManager(models.Manager):
# def get_primary_wallet(self):
# try:
# self.get(primary=True, wallet_type="EVM")
# except Wallet.DoesNotExist:
# return None


class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.PROTECT, related_name="profile")
initial_context_id = models.CharField(max_length=512, unique=True)
Expand Down Expand Up @@ -68,6 +76,9 @@ def is_aura_verified(self):

return is_verified

def owns_wallet(self, wallet_address):
return self.wallets.filter(address=wallet_address).exists()

def save(self, *args, **kwargs):
super().save(*args, **kwargs)

Expand All @@ -94,12 +105,11 @@ class Wallet(models.Model):
UserProfile, on_delete=models.PROTECT, related_name="wallets"
)
address = models.CharField(max_length=512, unique=True)
# primary = models.BooleanField(default=False, null=False, blank=False)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)

class Meta:
unique_together = (("wallet_type", "user_profile"),)
# objects = WalletManager()

def __str__(self):
return (
f"{self.wallet_type} Wallet for profile with contextId "
f"{self.user_profile.initial_context_id}"
)
return f"{self.wallet_type} Wallet for profile with contextId \
{self.user_profile.initial_context_id}"
9 changes: 9 additions & 0 deletions authentication/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,12 @@ class IsAuraVerified(BasePermission):

def has_permission(self, request, view):
return bool(request.user.profile.is_aura_verified)


class IsOwner(BasePermission):
"""
Just owner has can access
"""

def has_object_permission(self, request, view, obj):
return obj.user_profile == request.user.profile
47 changes: 20 additions & 27 deletions authentication/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from rest_framework import serializers
from rest_framework.authtoken.models import Token

from authentication.helpers import verify_signature_eth_scheme
from authentication.models import UserProfile, Wallet


Expand All @@ -22,36 +23,34 @@ def update(self, instance, validated_data):
pass


# class SetUsernameSerializer(serializers.Serializer):
# username = UsernameRequestSerializer.username
class WalletSerializer(serializers.ModelSerializer):
signature = serializers.CharField(required=True, max_length=150, write_only=True)
message = serializers.CharField(required=True, max_length=150, write_only=True)

# def save(self, user_profile):
# username = self.validated_data.get("username")
class Meta:
model = Wallet
fields = ["pk", "wallet_type", "address", "signature", "message"]

# try:
# user_profile.username = username
# user_profile.save()
# return {"message": "Username Set"}
def is_valid(self, raise_exception=False):
super_is_validated = super().is_valid(raise_exception)

# except IntegrityError:
# raise ValidationError(
# {"message": "This username already exists. Try another one."}
# )
address = self.validated_data.get("address")
message = self.validated_data.get("message")
signature = self.validated_data.get("signature")

signature_is_valid = verify_signature_eth_scheme(address, message, signature)

class WalletSerializer(serializers.ModelSerializer):
class Meta:
model = Wallet
fields = [
"pk",
"wallet_type",
"address",
]
if not signature_is_valid and raise_exception:
raise serializers.ValidationError("Signature is not valid")

self.validated_data.pop("signature", None)
self.validated_data.pop("message", None)

return super_is_validated and signature_is_valid


class ProfileSerializer(serializers.ModelSerializer):
wallets = WalletSerializer(many=True, read_only=True)
# total_round_claims_remaining = serializers.SerializerMethodField()
token = serializers.SerializerMethodField()

class Meta:
Expand All @@ -63,19 +62,13 @@ class Meta:
"initial_context_id",
"is_meet_verified",
"is_aura_verified",
# "total_round_claims_remaining",
"wallets",
]

def get_token(self, instance):
token, bol = Token.objects.get_or_create(user=instance.user)
return token.key

# def get_total_round_claims_remaining(self, instance):
# gs = GlobalSettings.objects.first()
# if gs is not None:
# return gs.gastap_round_claim_limit - LimitedChainClaimManager.get_total_round_claims(instance)


class SimpleProfilerSerializer(serializers.ModelSerializer):
wallets = WalletSerializer(many=True, read_only=True)
Expand Down
Loading