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

devel: rest api token auth #469

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion devel/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def clean_pgp_key(self):

class Meta:
model = UserProfile
exclude = ('allowed_repos', 'user', 'repos_auth_token')
exclude = ('allowed_repos', 'user', 'repos_auth_token', 'api_token')
widgets = {
'yob': NumberInput(attrs={'min': 1950, 'max': date.today().year - 10}),
}
Expand Down
44 changes: 44 additions & 0 deletions devel/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,55 @@
from django.contrib.auth.models import User, Group
from django_countries.fields import CountryField
from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.exceptions import ImproperlyConfigured
from django.utils.deprecation import MiddlewareMixin

from .fields import PGPKeyField
from main.utils import make_choice, set_created_field

from planet.models import Feed


class AuthTokenBackend(object):
def authenticate(self, request, username=None, password=None):
if 'X-Archweb-Token' in request.headers:
try:
profile = UserProfile.objects.get(api_token=request.headers['X-Archweb-Token'])
except UserProfile.DoesNotExist:
return None

print(profile)
return profile.user
return None

class AuthTokenMiddleware(MiddlewareMixin):
header = "X-Archweb-Token"

def process_request(self, request):
print("process", request)
# AuthenticationMiddleware is required so that request.user exists.
if not hasattr(request, "user"):
raise ImproperlyConfigured(
"The Django token user auth middleware requires the"
" authentication middleware to be installed. Edit your"
" MIDDLEWARE setting to insert"
" 'django.contrib.auth.middleware.AuthenticationMiddleware'"
" before the RemoteUserMiddleware class."
)
try:
token = request.headers[self.header]
print(token)
except KeyError:
return

try:
profile = UserProfile.objects.get(api_token=token)
except UserProfile.DoesNotExist:
return None

request.user = profile.user


class UserProfile(models.Model):
latin_name = models.CharField(
max_length=255, null=True, blank=True, help_text="Latin-form name; used only for non-Latin full names")
Expand Down Expand Up @@ -56,6 +98,7 @@ class UserProfile(models.Model):
rebuilderd_updates = models.BooleanField(
default=False, help_text='Receive reproducible build package updates')
repos_auth_token = models.CharField(max_length=32, null=True, blank=True)
api_token = models.CharField(max_length=32, null=True, blank=True)
last_modified = models.DateTimeField(editable=False)

class Meta:
Expand Down Expand Up @@ -198,6 +241,7 @@ def delete_user_model(sender, **kwargs):
return

userprofile.repos_auth_token = ''
userprofile.api_token = ''

Feed.objects.filter(website_rss=userprofile.website_rss).delete()

Expand Down
8 changes: 7 additions & 1 deletion devel/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ def tier0_mirror_auth(request):
def change_profile(request):
profile, _ = UserProfile.objects.get_or_create(user=request.user)
if request.POST:
# Generate token
if request.POST.get('api_token'):
profile.api_token = generate_repo_auth_token()
profile.save()

form = ProfileForm(request.POST)
profile_form = UserProfileForm(request.POST,
request.FILES,
Expand Down Expand Up @@ -257,7 +262,8 @@ def change_profile(request):
profile_form = UserProfileForm(instance=profile)
return render(request, 'devel/profile.html',
{'form': form,
'profile_form': profile_form})
'profile_form': profile_form,
'profile': profile})


@login_required
Expand Down
5 changes: 5 additions & 0 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,16 @@
# Set django's User stuff to use our profile model
AUTH_PROFILE_MODULE = 'devel.UserProfile'

AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)

MIDDLEWARE = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'devel.models.AuthTokenMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
Expand Down
15 changes: 15 additions & 0 deletions templates/devel/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,20 @@ <h2>Developer Profile</h2>
<p><label></label> <input title="Save changes" type="submit" value="Save" /></p>
</form>

<form id="api-profile-form" enctype="multipart/form-data" method="post" action="">{% csrf_token %}
<h3>API token</h3>
<p>Token for completing todolist items with for example, rebuild-todo</p>
{% if profile.api_token is None %}
<fieldset>
<input type="hidden" name="api_token" id="api_token" value="generate">
</fieldset>
<p><label></label> <input title="Generate token" type="submit" value="Generate API Token" /></p>
{% else %}
<fieldset>
<label>Token:</label>
{{ profile.api_token }}
</fieldset>
{% endif %}
</form>
</div>
{% endblock %}