Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

devel: rest api token auth#469

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
jelly wants to merge1 commit intoarchlinux:master
base:master
Choose a base branch
Loading
fromjelly:rest-token-complete-todolist
Draft
Show file tree
Hide file tree
Changes fromall 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
devel: rest api token auth
Implement a simple token authentication header for various "restish"endpoints we might want for adoption/disowning of packages.
  • Loading branch information
@jelly
jelly committedJul 3, 2023
commit22af6e1ebe6ee9e0cb56ca9201273f6df5232a22
2 changes: 1 addition & 1 deletiondevel/forms.py
View file
Open in desktop
Original file line numberDiff line numberDiff 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 deletionsdevel/models.py
View file
Open in desktop
Original file line numberDiff line numberDiff 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:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Wouldn't it make sense to useAuthorization: Bearer as header, this is a quite widely used way for such API and would also allow a lot of HTTP clients to use implemented helper methods for authenticate a request with a token. Otherwise you'd need to pass around custom header strings likeX-Archweb-Token.
What are your thoughts about this?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Sounds fine to me, it shouldn't conflict with things I suppose.

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 DownExpand 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 DownExpand 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 deletiondevel/views.py
View file
Open in desktop
Original file line numberDiff line numberDiff 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 DownExpand 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 deletionssettings.py
View file
Open in desktop
Original file line numberDiff line numberDiff 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 deletionstemplates/devel/profile.html
View file
Open in desktop
Original file line numberDiff line numberDiff 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 %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I assume it would be a good pattern to be able to revoke a token, or to phrase it differently: Generate a new token and invalidate the existing one.
I'd probably propose something like only showing the token once when the generate button is clicked and otherwise show an invalidate/regenerate button instead. We should hide the token after generating it.

<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 %}

[8]ページ先頭

©2009-2025 Movatter.jp