Parcourir la source

Merge branch 'ercare-v1' into 'master'

Ercare v1

See merge request ByteTrek-Projects/review-automation-backend!1
Mohidul Islam il y a 5 ans
Parent
commit
56ef6c058d

+ 9 - 3
gauth/admin.py

@@ -1,9 +1,15 @@
 from django.contrib import admin
 from django.contrib import admin
-from .models import UserModel
+from .models import UserModel, Location
 
 
 
 
 class UserModelAdmin(admin.ModelAdmin):
 class UserModelAdmin(admin.ModelAdmin):
-    list_display = ['user', 'refresh_token']
+    list_display = ['user', 'refresh_token', 'gmb_account_id']
 
 
 
 
-admin.site.register(UserModel, UserModelAdmin)
+class LocationsAdmin(admin.ModelAdmin):
+    list_display = ['location_id', 'location_name', 'website_url', 'display_name']
+
+
+admin.site.register(Location, LocationsAdmin)
+
+admin.site.register(UserModel, UserModelAdmin)

+ 32 - 8
gauth/utils.py → gauth/auth_utils.py

@@ -1,7 +1,9 @@
+from django.contrib.auth.models import User
 from django.utils import timezone
 from django.utils import timezone
 from requests import post
 from requests import post
 from django.conf import settings
 from django.conf import settings
 from .models import UserModel
 from .models import UserModel
+from requests import get
 
 
 
 
 def has_expired(credentials):
 def has_expired(credentials):
@@ -11,7 +13,24 @@ def has_expired(credentials):
 
 
 
 
 def get_access_token(request):
 def get_access_token(request):
-    uid = request.user.id
+    if 'credentials' in request.session and not has_expired(request.session['credentials']):
+        cred = request.session['credentials']
+        return cred['access_token']
+
+    access_token, expires_in = refresh_access_token()
+    expired_at = timezone.datetime.now() + timezone.timedelta(seconds=expires_in)
+    expiry = str(expired_at)
+    credentials = {
+        'access_token': access_token,
+        'expiry': expiry
+    }
+    request.session['credentials'] = credentials
+    return credentials['access_token']
+
+
+def refresh_access_token():
+    user = User.objects.filter(username='admin@ercare').first()
+    uid = user.id
     user = UserModel.objects.filter(pk=uid).first()
     user = UserModel.objects.filter(pk=uid).first()
     if user:
     if user:
         refresh_token = user.refresh_token
         refresh_token = user.refresh_token
@@ -31,11 +50,16 @@ def get_access_token(request):
     response = post(token_uri, data=params).json()
     response = post(token_uri, data=params).json()
     access_token = response['access_token']
     access_token = response['access_token']
     expires_in = response['expires_in']
     expires_in = response['expires_in']
-    expired_at = timezone.datetime.now() + timezone.timedelta(seconds=expires_in)
-    expiry = str(expired_at)
-    credentials = {
-        'access_token': access_token,
-        'expiry': expiry
+    return access_token, expires_in
+
+
+def get_google_account_id(access_token):
+    uri = 'https://mybusiness.googleapis.com/v4/accounts'
+    headers = {
+        'authorization': 'Bearer '+access_token,
+        'content-type': 'application/json'
     }
     }
-    request.session['credentials'] = credentials
-    return response['access_token']
+    res = get(uri, headers=headers).json()
+    accounts_name = res['accounts'][0]['name']
+    id = accounts_name.split('/')[-1]
+    return id

+ 39 - 0
gauth/location_utils.py

@@ -0,0 +1,39 @@
+from django.contrib.auth.models import User
+from requests import get
+from .auth_utils import refresh_access_token
+from .models import UserModel, Location
+
+
+def get_all_location_ids():
+    locations = Location.objects.only('location_id')
+    ids = [loc.location_id for loc in locations]
+    '''
+    There is a location which we don't need to add into database.
+    It is a Medical Billing Service, That's why it is nothing to do with review. 
+    '''
+    ids.remove('5397588228065547694')
+    return ids
+
+
+def populate_locations():
+    access_token, _ = refresh_access_token()
+    user = User.objects.get(username='admin@ercare')
+    gmb_id = UserModel.objects.get(user=user).gmb_account_id
+    url = 'https://mybusiness.googleapis.com/v4/accounts/' + gmb_id + '/locations'
+    headers = {
+        'authorization': 'Bearer ' + access_token,
+        'content-type': 'application/json'
+    }
+    res = get(url, headers=headers).json()
+    locations = res['locations']
+    for loc in locations:
+        # loc['name'] = 'accounts/103266181421855655295/locations/8916258876770296726'
+        loc_id = loc['name'].split('/')[-1]
+        location_ids = get_all_location_ids()
+        if loc_id in location_ids:
+            continue
+        loc_name = loc['locationName']
+        loc_website = loc['websiteUrl']
+        loc_display = loc['primaryCategory']['displayName']
+        location = Location.objects.create(location_id=loc_id, location_name=loc_name, website_url=loc_website, display_name=loc_display, owner=user)
+        location.save()

+ 2 - 1
gauth/migrations/0001_initial.py

@@ -1,4 +1,4 @@
-# Generated by Django 3.0 on 2019-12-12 09:13
+# Generated by Django 3.0 on 2019-12-26 13:17
 
 
 from django.conf import settings
 from django.conf import settings
 from django.db import migrations, models
 from django.db import migrations, models
@@ -19,6 +19,7 @@ class Migration(migrations.Migration):
             fields=[
             fields=[
                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('refresh_token', models.CharField(max_length=30)),
                 ('refresh_token', models.CharField(max_length=30)),
+                ('gmb_account_id', models.CharField(max_length=30)),
                 ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='token_of', to=settings.AUTH_USER_MODEL)),
                 ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='token_of', to=settings.AUTH_USER_MODEL)),
             ],
             ],
         ),
         ),

+ 23 - 0
gauth/migrations/0002_auto_20191229_0659.py

@@ -0,0 +1,23 @@
+# Generated by Django 3.0 on 2019-12-29 06:59
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('gauth', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='usermodel',
+            name='gmb_account_id',
+            field=models.CharField(blank=True, max_length=30, null=True),
+        ),
+        migrations.AlterField(
+            model_name='usermodel',
+            name='refresh_token',
+            field=models.CharField(blank=True, max_length=30, null=True),
+        ),
+    ]

+ 27 - 0
gauth/migrations/0003_location.py

@@ -0,0 +1,27 @@
+# Generated by Django 3.0 on 2019-12-29 09:56
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('gauth', '0002_auto_20191229_0659'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Location',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('location_id', models.CharField(max_length=50)),
+                ('location_name', models.CharField(max_length=50)),
+                ('website_url', models.URLField()),
+                ('display_name', models.CharField(max_length=50)),
+                ('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]

+ 18 - 0
gauth/migrations/0004_auto_20191229_1033.py

@@ -0,0 +1,18 @@
+# Generated by Django 3.0 on 2019-12-29 10:33
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('gauth', '0003_location'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='location',
+            name='location_id',
+            field=models.CharField(max_length=50, unique=True),
+        ),
+    ]

+ 14 - 1
gauth/models.py

@@ -4,7 +4,20 @@ from django.contrib.auth.models import User
 
 
 class UserModel(models.Model):
 class UserModel(models.Model):
     user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='token_of')
     user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='token_of')
-    refresh_token = models.CharField(max_length=30)
+    refresh_token = models.CharField(max_length=30, null=True, blank=True)
+    gmb_account_id = models.CharField(max_length=30, null=True, blank=True)
 
 
     def __str__(self):
     def __str__(self):
         return self.user.username
         return self.user.username
+
+
+class Location(models.Model):
+    location_id = models.CharField(max_length=50, unique=True)
+    location_name = models.CharField(max_length=50)
+    website_url = models.URLField()
+    display_name = models.CharField(max_length=50)
+    owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
+
+    def __str__(self):
+        return self.display_name
+

+ 3 - 2
gauth/urls.py

@@ -1,8 +1,9 @@
 from django.urls import path
 from django.urls import path
-from .views import index, authorize, oauth2callback
+from .views import google_auth, authorize, oauth2callback, index
 
 
 urlpatterns = [
 urlpatterns = [
     path('', index, name='home'),
     path('', index, name='home'),
-    path('authorize/', authorize, name='authorize'),
+    path('gmb-authenticate/', google_auth, name='gmb-auth'),
+    path('authorize', authorize, name='authorize'),
     path('oauth2callback', oauth2callback, name='oauth2callback'),
     path('oauth2callback', oauth2callback, name='oauth2callback'),
 ]
 ]

+ 22 - 17
gauth/views.py

@@ -3,25 +3,13 @@ from django.shortcuts import redirect
 from django.urls import reverse
 from django.urls import reverse
 import google_auth_oauthlib.flow
 import google_auth_oauthlib.flow
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.decorators import login_required
+from django.contrib.auth.models import User
 
 
-from .utils import get_access_token, has_expired
+from .auth_utils import get_access_token, get_google_account_id
 
 
 from .models import UserModel
 from .models import UserModel
 
 
 
 
-@login_required
-def index(request):
-    uid = request.user.id
-    user = UserModel.objects.filter(pk=uid).first()
-    if not user:
-        return redirect(reverse('authorize'))
-    if 'credentials' not in request.session or has_expired(request.session['credentials']):
-        get_access_token(request)
-    cred = request.session['credentials']
-
-    return HttpResponse(cred['access_token'])
-
-
 CLIENT_SECRETS_FILE = "client_secrets.json"
 CLIENT_SECRETS_FILE = "client_secrets.json"
 SCOPES = ['https://www.googleapis.com/auth/business.manage']
 SCOPES = ['https://www.googleapis.com/auth/business.manage']
 flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
 flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
@@ -30,6 +18,20 @@ flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
         redirect_uri="http://127.0.0.1:8000/oauth2callback")
         redirect_uri="http://127.0.0.1:8000/oauth2callback")
 
 
 
 
+def index(request):
+    get_access_token(request)
+    cred = request.session['credentials']
+    return HttpResponse(cred['access_token'])
+
+
+@login_required
+def google_auth(request):
+    user = User.objects.filter(username='admin@ercare').first()
+    if not user:
+        return HttpResponse('<h1>You have to have a user account with username "admin@ercare". Please create a superuser using manage.py createsuperuser</h2>')
+    return redirect(reverse('authorize'))
+
+
 def authorize(request):
 def authorize(request):
     authorization_url, state = flow.authorization_url(access_type='offline')
     authorization_url, state = flow.authorization_url(access_type='offline')
 
 
@@ -47,10 +49,13 @@ def oauth2callback(request):
     flow.fetch_token(code=code)
     flow.fetch_token(code=code)
 
 
     credentials = flow.credentials
     credentials = flow.credentials
-    request.session['credentials'] = credentials_to_dict(credentials)
-    refresh_token = credentials.refresh_token
-    user_model = UserModel.objects.create(user=request.user, refresh_token=refresh_token)
+    account_id = get_google_account_id(credentials.token)
+    user = User.objects.filter(username='admin@ercare').first()
+    user_model, created = UserModel.objects.get_or_create(user=user)
+    user_model.refresh_token = credentials.refresh_token
+    user_model.gmb_account_id = account_id
     user_model.save()
     user_model.save()
+    request.session['credentials'] = credentials_to_dict(credentials)
     return redirect(reverse('home'))
     return redirect(reverse('home'))
 
 
 
 

+ 0 - 0
review/__init__.py


+ 3 - 0
review/admin.py

@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.

+ 5 - 0
review/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class ReviewConfig(AppConfig):
+    name = 'review'

+ 48 - 0
review/migrations/0001_initial.py

@@ -0,0 +1,48 @@
+# Generated by Django 3.0 on 2019-12-26 13:12
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Location',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('location_id', models.CharField(max_length=50)),
+                ('location_name', models.CharField(max_length=50)),
+                ('website_url', models.URLField()),
+                ('display_name', models.CharField(max_length=50)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Reply',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('replied_text', models.CharField(max_length=500)),
+                ('create_time', models.DateTimeField()),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Review',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('review_id', models.CharField(max_length=50)),
+                ('comment', models.CharField(max_length=1000)),
+                ('create_time', models.DateTimeField()),
+                ('update_time', models.DateTimeField()),
+                ('star_rating', models.IntegerField()),
+                ('reviewer_name', models.CharField(max_length=50)),
+                ('reviewer_photo', models.URLField()),
+                ('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='review.Location')),
+                ('reply', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='review.Reply')),
+            ],
+        ),
+    ]

+ 26 - 0
review/migrations/0002_auto_20191229_0603.py

@@ -0,0 +1,26 @@
+# Generated by Django 3.0 on 2019-12-29 06:03
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('review', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='location',
+            name='owner',
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
+        ),
+        migrations.AlterField(
+            model_name='review',
+            name='location',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='review.Location'),
+        ),
+    ]

+ 23 - 0
review/migrations/0003_auto_20191229_0956.py

@@ -0,0 +1,23 @@
+# Generated by Django 3.0 on 2019-12-29 09:56
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('gauth', '0003_location'),
+        ('review', '0002_auto_20191229_0603'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='review',
+            name='location',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='gauth.Location'),
+        ),
+        migrations.DeleteModel(
+            name='Location',
+        ),
+    ]

+ 0 - 0
review/migrations/__init__.py


+ 26 - 0
review/models.py

@@ -0,0 +1,26 @@
+from django.db import models
+from django.contrib.auth.models import User
+from gauth.models import Location
+
+
+class Reply(models.Model):
+    replied_text = models.CharField(max_length=500)
+    create_time = models.DateTimeField()
+
+    def __str__(self):
+        return self.replied_text
+
+
+class Review(models.Model):
+    review_id = models.CharField(max_length=50)
+    comment = models.CharField(max_length=1000)
+    create_time = models.DateTimeField()
+    update_time = models.DateTimeField()
+    star_rating = models.IntegerField()
+    reviewer_name = models.CharField(max_length=50)
+    reviewer_photo = models.URLField()
+    location = models.ForeignKey(Location, on_delete=models.DO_NOTHING)
+    reply = models.OneToOneField(Reply, on_delete=models.CASCADE)
+
+    def __str__(self):
+        return f'{self.reviewer_name} - {self.comment}'

+ 3 - 0
review/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 3 - 0
review/views.py

@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.

+ 1 - 0
review_automation/settings.py

@@ -24,6 +24,7 @@ INSTALLED_APPS = [
     'django.contrib.staticfiles',
     'django.contrib.staticfiles',
 
 
     'gauth.apps.GauthConfig',
     'gauth.apps.GauthConfig',
+    'review.apps.ReviewConfig',
 ]
 ]
 
 
 MIDDLEWARE = [
 MIDDLEWARE = [