Feature: Add frontend support for API token and fix bug

This commit is contained in:
winkidney
2022-02-18 21:17:27 -08:00
parent 2892ebb333
commit a59fce881f
7 changed files with 138 additions and 11 deletions

View File

@@ -56,6 +56,11 @@
class="navbar-item">
Pins
</router-link>
<router-link
:to="{ name: 'profile4user', params: {username: user.meta.username} }"
class="navbar-item">
Profile
</router-link>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">

View File

@@ -47,6 +47,16 @@
<span>Boards</span>
</a>
</li>
<li :class="trueFalse2Class(inProfile)">
<a @click="go2UserProfile">
<b-icon
type="is-dark"
icon="account"
custom-size="mdi-24px">
</b-icon>
<span>Profile</span>
</a>
</li>
</ul>
</div>
@@ -71,6 +81,10 @@ export default {
type: Boolean,
default: false,
},
inProfile: {
type: Boolean,
default: false,
},
},
data() {
return {
@@ -91,6 +105,11 @@ export default {
{ name: 'boards4user', params: { username: this.username } },
);
},
go2UserProfile() {
this.$router.push(
{ name: 'profile4user', params: { username: this.username } },
);
},
go2UserPins() {
this.$router.push(
{ name: 'user', params: { user: this.username } },

View File

@@ -0,0 +1,41 @@
<template>
<div class="profile-container">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Token
</p>
</header>
<div class="card-content">
<div class="content">
<p>Your Token is:</p>
<pre>{{ token }}</pre>
Please read <a href="#">DRF API Documentation</a> for more detail to know how to use it.
<br>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'profile',
props: ['token'],
data() {
return {};
},
};
</script>
<style scoped lang="scss">
.profile-container {
margin-top: 2rem;
margin-left: auto;
margin-right: auto;
box-shadow: 5px 5px 2px 1px rgba(0, 0, 255, .1);
}
@import '../utils/grid-layout';
@include screen-grid-layout(".profile-container");
</style>

View File

@@ -6,6 +6,7 @@ import Pins4User from '../views/Pins4User.vue';
import Pins4Board from '../views/Pins4Board.vue';
import Pins4Id from '../views/Pins4Id.vue';
import Boards4User from '../views/Boards4User.vue';
import Profile4User from '../views/Profile4User.vue';
import PinCreate from '../views/PinCreate.vue';
import Search from '../views/Search.vue';
import PageNotFound from '../views/PageNotFound.vue';
@@ -43,6 +44,11 @@ const routes = [
name: 'boards4user',
component: Boards4User,
},
{
path: '/profile/:username',
name: 'profile4user',
component: Profile4User,
},
{
path: '/pin-creation/from-url',
name: 'pin-creation-from-url',

View File

@@ -0,0 +1,54 @@
<template>
<div class="profile-for-user">
<PHeader></PHeader>
<UserProfileCard :in-profile="true" :username="filters.userFilter"></UserProfileCard>
<Profile :token="profile.token"></Profile>
</div>
</template>
<script>
import PHeader from '../components/PHeader.vue';
import UserProfileCard from '../components/UserProfileCard.vue';
import Profile from '../components/user/profile.vue';
import api from '../components/api';
export default {
name: 'Profile4User',
data() {
return {
filters: { userFilter: null },
profile: {},
};
},
components: {
PHeader,
UserProfileCard,
Profile,
},
created() {
this.initializeBoard();
this.initializeUser();
},
beforeRouteUpdate(to, from, next) {
this.filters = { userFilter: to.params.username };
next();
},
methods: {
initializeBoard() {
this.filters = { userFilter: this.$route.params.username };
},
initializeUser() {
const self = this;
api.User.fetchUserInfo(false).then(
(user) => {
self.profile = user;
},
);
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>

View File

@@ -5,7 +5,17 @@ from django.db.models.signals import post_save
from django.dispatch import receiver
def create_token_if_necessary(user: BaseUser):
from rest_framework.authtoken.models import Token
token = Token.objects.filter(user=user).first()
if token is not None:
return token
else:
return Token.objects.create(user=user)
class User(BaseUser):
@property
def gravatar(self):
return hashlib.md5(self.email.encode('utf-8')).hexdigest()
@@ -13,15 +23,7 @@ class User(BaseUser):
class Meta:
proxy = True
def create_token_if_necessary(self):
from rest_framework.authtoken.models import Token
token = Token.objects.filter(user=self).first()
if token is not None:
return token
else:
return Token.objects.create(user=self)
@receiver(post_save, sender=User)
def create_profile(sender, instance: User, **kwargs):
instance.create_token_if_necessary()
create_token_if_necessary(instance)

View File

@@ -3,7 +3,7 @@ from django.contrib.auth import login
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from users.models import User
from users.models import User, create_token_if_necessary
class PublicUserSerializer(serializers.HyperlinkedModelSerializer):
@@ -77,4 +77,4 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
return user
def get_token(self, obj: User):
return obj.create_token_if_necessary().key
return create_token_if_necessary(obj).key