This commit is contained in:
Eugene Pankov 2021-07-22 21:34:05 +02:00
parent 08e8f07785
commit 0b0d711a08
No known key found for this signature in database
GPG Key ID: 5896FCBBDD1CF4F4
7 changed files with 55 additions and 16 deletions

View File

@ -21,9 +21,7 @@ export class LoginComponent {
constructor ( constructor (
private loginService: LoginService, private loginService: LoginService,
) { ) { }
this.providers = [this.providers[0]] // only keep GH for now
}
async ngOnInit () { async ngOnInit () {
await this.loginService.ready$.toPromise() await this.loginService.ready$.toPromise()

View File

@ -1,8 +1,15 @@
.modal-header .modal-header
h5.modal-title Settings h3.modal-title Settings
.modal-body .modal-body
.mb-3 .mb-3
h5 GitHub account
a.btn.btn-info(href='/api/1/auth/social/login/github')
fa-icon([icon]='_githubIcon', [fixedWidth]='true')
span Connect a GitHub account
.mb-3
h5 Connection gateway
.form-check.form-switch .form-check.form-switch
input.form-check-input( input.form-check-input(
type='checkbox', type='checkbox',

View File

@ -4,6 +4,7 @@ import { LoginService } from '../services/login.service'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { User } from '../api' import { User } from '../api'
import { AppConnectorService } from '../services/appConnector.service' import { AppConnectorService } from '../services/appConnector.service'
import { faGithub } from '@fortawesome/free-brands-svg-icons'
@Component({ @Component({
selector: 'settings-modal', selector: 'settings-modal',
@ -13,6 +14,7 @@ import { AppConnectorService } from '../services/appConnector.service'
export class SettingsModalComponent { export class SettingsModalComponent {
user: User user: User
customGatewayEnabled = false customGatewayEnabled = false
_githubIcon = faGithub
constructor ( constructor (
public appConnector: AppConnectorService, public appConnector: AppConnectorService,

View File

@ -1,6 +1,5 @@
import asyncio import asyncio
import random import random
from tabby.app.consumers import GatewayAdminConnection
from django.conf import settings from django.conf import settings
from django.contrib.auth import logout from django.contrib.auth import logout
from dataclasses import dataclass from dataclasses import dataclass
@ -14,8 +13,11 @@ from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet, ModelViewSet from rest_framework.viewsets import GenericViewSet, ModelViewSet
from rest_framework.serializers import ModelSerializer, Serializer from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework_dataclasses.serializers import DataclassSerializer from rest_framework_dataclasses.serializers import DataclassSerializer
from social_django.models import UserSocialAuth
from typing import List from typing import List
from .consumers import GatewayAdminConnection
from .sponsors import get_sponsor_usernames
from .models import Config, Gateway, User from .models import Config, Gateway, User
@ -98,6 +100,7 @@ class AppVersionViewSet(ListModelMixin, GenericViewSet):
class UserSerializer(ModelSerializer): class UserSerializer(ModelSerializer):
id = fields.IntegerField() id = fields.IntegerField()
is_pro = fields.SerializerMethodField() is_pro = fields.SerializerMethodField()
github_username = fields.SerializerMethodField()
class Meta: class Meta:
model = User model = User
@ -108,11 +111,22 @@ class UserSerializer(ModelSerializer):
'custom_connection_gateway', 'custom_connection_gateway',
'custom_connection_gateway_token', 'custom_connection_gateway_token',
'is_pro', 'is_pro',
'github_username',
) )
read_only_fields = ('id', 'username') read_only_fields = ('id', 'username')
def get_is_pro(self, obj): def get_is_pro(self, obj):
return False username = self.get_github_username(obj)
if not username:
return False
return username in get_sponsor_usernames()
def get_github_username(self, obj):
social_auth = UserSocialAuth.objects.filter(user=obj, provider='github').first()
if not social_auth:
return None
return social_auth.extra_data.get('login')
class UserViewSet(RetrieveModelMixin, UpdateModelMixin, GenericViewSet): class UserViewSet(RetrieveModelMixin, UpdateModelMixin, GenericViewSet):

View File

@ -16,8 +16,8 @@ class Config(models.Model):
class User(AbstractUser): class User(AbstractUser):
active_config = models.ForeignKey(Config, null=True, on_delete=models.SET_NULL, related_name='+') active_config = models.ForeignKey(Config, null=True, on_delete=models.SET_NULL, related_name='+')
active_version = models.CharField(max_length=32, null=True) active_version = models.CharField(max_length=32, null=True)
custom_connection_gateway = models.CharField(max_length=255, null=True) custom_connection_gateway = models.CharField(max_length=255, null=True, blank=True)
custom_connection_gateway_token = models.CharField(max_length=255, null=True) custom_connection_gateway_token = models.CharField(max_length=255, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True) modified_at = models.DateTimeField(auto_now=True)

View File

@ -1,12 +1,14 @@
from django.conf import settings from django.conf import settings
from django.core.cache import cache
from gql import Client, gql from gql import Client, gql
from gql.transport.requests import RequestsHTTPTransport from gql.transport.requests import RequestsHTTPTransport
GQL_ENDPOINT = 'https://api.github.com/graphql' GQL_ENDPOINT = 'https://api.github.com/graphql'
CACHE_KEY = 'cached-sponsors'
def get_sponsor_usernames(): def fetch_sponsor_usernames():
client = Client( client = Client(
transport=RequestsHTTPTransport( transport=RequestsHTTPTransport(
url=GQL_ENDPOINT, url=GQL_ENDPOINT,
@ -61,3 +63,9 @@ def get_sponsor_usernames():
result.append(node['sponsor']['login']) result.append(node['sponsor']['login'])
return result return result
def get_sponsor_usernames():
if not cache.get(CACHE_KEY):
cache.set(CACHE_KEY, fetch_sponsor_usernames(), timeout=30)
return cache.get(CACHE_KEY)

View File

@ -70,17 +70,15 @@ TEMPLATES = [
ASGI_APPLICATION = 'tabby.asgi.application' ASGI_APPLICATION = 'tabby.asgi.application'
WSGI_APPLICATION = 'tabby.wsgi.application' WSGI_APPLICATION = 'tabby.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = { DATABASES = {
'default': dj_database_url.config(conn_max_age=600) 'default': dj_database_url.config(conn_max_age=600)
} }
CACHES = {
# Password validation 'default': {
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
@ -163,6 +161,18 @@ AUTHENTICATION_BACKENDS = (
) )
SOCIAL_AUTH_GITHUB_SCOPE = ['read:user', 'user:email'] SOCIAL_AUTH_GITHUB_SCOPE = ['read:user', 'user:email']
SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'social_core.pipeline.social_auth.associate_by_email',
'social_core.pipeline.user.create_user',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
)
LOGIN_REDIRECT_URL = '/app' LOGIN_REDIRECT_URL = '/app'