[backend + frontend]: Добавлена базовая регистрация

This commit is contained in:
2022-09-12 23:57:40 +03:00
parent 818bb9db81
commit ede65b0147
21 changed files with 198 additions and 29 deletions

View File

@@ -1,10 +1,35 @@
asgiref==3.5.2
backports.zoneinfo==0.2.1
certifi==2022.6.15.1
cffi==1.15.1
charset-normalizer==2.1.1
coreapi==2.3.3
coreschema==0.0.4
cryptography==38.0.1
defusedxml==0.7.1
Django==4.1.1
django-cors-headers==3.13.0
django-filter==22.1
django-templated-mail==1.1.1
djangorestframework==3.13.1
djangorestframework-gis==1.0
djangorestframework-simplejwt==4.8.0
djoser==2.1.0
idna==3.3
itypes==1.2.0
Jinja2==3.1.2
MarkupSafe==2.1.1
oauthlib==3.2.1
psycopg2==2.9.3
pycparser==2.21
PyJWT==2.4.0
python3-openid==3.2.0
pytz==2022.2.1
requests==2.28.1
requests-oauthlib==1.3.1
six==1.16.0
social-auth-app-django==4.0.0
social-auth-core==4.3.0
sqlparse==0.4.2
uritemplate==4.1.1
urllib3==1.26.12

View File

@@ -4,5 +4,5 @@ from django.utils.translation import gettext_lazy
class AuthConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "authentication"
verbose_name = gettext_lazy("authentication")
name = "accounts"
verbose_name = gettext_lazy("accounts")

View File

@@ -0,0 +1,14 @@
from django.urls import path
from django.urls import include
from accounts.views import CustomTokenObtainPairView
urlpatterns = [
path("", include("djoser.urls")),
path(
"auth/jwt/create",
CustomTokenObtainPairView.as_view(),
name="custom_token_obtain_pair",
),
path("auth/", include("djoser.urls.jwt")),
]

View File

@@ -0,0 +1,13 @@
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
data = super().validate(attrs)
data["username"] = self.user.username
return data
class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer

View File

@@ -1,9 +0,0 @@
from django.urls import path
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.views import TokenRefreshView
urlpatterns = [
path("token", TokenObtainPairView.as_view(), name="token_obtain_pair"),
path("token/refresh", TokenRefreshView.as_view(), name="token_refresh"),
]

View File

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

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-10 14:48+0300\n"
"POT-Creation-Date: 2022-09-12 23:55+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -20,6 +20,10 @@ msgstr ""
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
#: accounts/apps.py:8
msgid "accounts"
msgstr "аккаунты"
#: facilities/apps.py:8 facilities/models.py:18
msgid "facilities"
msgstr "заведения"

View File

@@ -43,11 +43,11 @@ INSTALLED_APPS = [
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.gis",
"djoser",
"rest_framework",
"rest_framework_simplejwt",
"rest_framework_gis",
"corsheaders",
"authentication",
"accounts",
"facilities",
]
@@ -128,9 +128,12 @@ STATIC_URL = "static/"
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
)
),
}
SIMPLE_JWT = {
"AUTH_HEADER_TYPES": ("JWT",),
}

View File

@@ -11,3 +11,7 @@ DATABASES = {
"PORT": "5432",
}
}
CORS_ALLOWED_ORIGINS = [
"http://localhost:8080",
]

View File

@@ -19,6 +19,6 @@ from django.urls import include
urlpatterns = [
path("admin/", admin.site.urls),
path("api/auth/", include("authentication.urls")),
path("api/accounts/", include("accounts.urls")),
path("api/facilities/", include("facilities.urls")),
]

View File

@@ -5,6 +5,7 @@
<div class="card card-container">
<Form @submit="handleLogin" :validation-schema="schema"
class="p-4 p-md-5 border rounded-3 bg-light">
<h5 class="card-title">Login</h5>
<div class="form-group">
<label for="username">Username</label>
<Field name="username" type="text" class="form-control" />
@@ -61,7 +62,7 @@ export default {
},
created() {
if (this.loggedIn) {
this.$router.push("/profile");
this.$router.push("/");
}
},
methods: {
@@ -69,7 +70,7 @@ export default {
this.loading = true;
this.$store.dispatch("auth/login", user).then(
() => {
this.$router.push("/profile");
this.$router.push("/");
},
(error) => {
this.loading = false;

View File

@@ -0,0 +1,112 @@
<template>
<div class="container col-xl-10 col-xxl-8 px-4 py-5">
<div class="row align-items-center g-lg-5 py-5">
<div class="col-md-10 mx-auto col-lg-5">
<div class="card card-container">
<Form @submit="handleRegister" :validation-schema="schema"
class="p-4 p-md-5 border rounded-3 bg-light">
<h5 class="card-title">Registration</h5>
<div v-if="!successful">
<div class="form-group">
<label for="username">Username</label>
<Field name="username" type="text" class="form-control" />
<ErrorMessage name="username" class="error-feedback" />
</div>
<div class="form-group">
<label for="email">Email</label>
<Field name="email" type="email" class="form-control" />
<ErrorMessage name="email" class="error-feedback" />
</div>
<div class="form-group">
<label for="password">Password</label>
<Field name="password" type="password" class="form-control" />
<ErrorMessage name="password" class="error-feedback" />
</div>
<br>
<div class="form-group">
<button class="btn btn-primary btn-block" :disabled="loading">
<span v-show="loading" class="spinner-border spinner-border-sm"></span>
Sign Up
</button>
</div>
</div>
</Form>
<div v-if="message" class="alert" :class="successful ? 'alert-success' : 'alert-danger'">
{{ message }}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";
export default {
name: "RegistrationPage",
components: {
Form,
Field,
ErrorMessage,
},
data() {
const schema = yup.object().shape({
username: yup
.string()
.required("Username is required!")
.min(3, "Must be at least 3 characters!")
.max(20, "Must be maximum 20 characters!"),
email: yup
.string()
.required("Email is required!")
.email("Email is invalid!")
.max(50, "Must be maximum 50 characters!"),
password: yup
.string()
.required("Password is required!")
.min(6, "Must be at least 6 characters!")
.max(40, "Must be maximum 40 characters!"),
});
return {
successful: false,
loading: false,
message: "",
schema,
};
},
computed: {
loggedIn() {
return this.$store.state.auth.status.loggedIn;
},
},
mounted() {
if (this.loggedIn) {
this.$router.push("/");
}
},
methods: {
handleRegister(user) {
this.message = "";
this.successful = false;
this.loading = true;
this.$store.dispatch("auth/register", user).then(
(data) => {
this.message = data.message;
this.successful = true;
this.loading = false;
},
(error) => {
this.message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
this.successful = false;
this.loading = false;
}
);
},
},
};
</script>

View File

@@ -1,6 +1,7 @@
import { createWebHistory, createRouter } from "vue-router";
import MapPage from "./components/MapPage.vue";
import LoginPage from "./components/LoginPage.vue";
import RegistrationPage from "./components/RegistrationPage.vue";
const routes = [
{
path: "/",
@@ -11,6 +12,10 @@ const routes = [
path: "/login",
component: LoginPage,
},
{
path: "/register",
component: RegistrationPage,
},
];
const router = createRouter({
history: createWebHistory(),

View File

@@ -1,7 +1,7 @@
export default function authHeader() {
let user = JSON.parse(localStorage.getItem('user'));
if (user && user.accessToken) {
return { Authorization: 'Bearer ' + user.accessToken };
if (user && user.access) {
return { Authorization: 'Bearer ' + user.access };
} else {
return {};
}

View File

@@ -1,14 +1,14 @@
import axios from "axios";
const API_URL = "http://localhost:8000/api/auth/";
const API_URL = "http://127.0.0.1:8000/api/accounts/";
class AuthService {
login(user) {
return axios
.post(API_URL + "token", {
.post(API_URL + "auth/jwt/create", {
username: user.username,
password: user.password,
})
.then((response) => {
if (response.data.accessToken) {
if (response.data.access) {
localStorage.setItem("user", JSON.stringify(response.data));
}
return response.data;
@@ -18,7 +18,7 @@ class AuthService {
localStorage.removeItem("user");
}
register(user) {
return axios.post(API_URL + "signup", {
return axios.post(API_URL + "users/", {
username: user.username,
email: user.email,
password: user.password,

View File

@@ -1,6 +1,6 @@
import axios from 'axios';
import authHeader from './auth-header';
const API_URL = 'http://localhost:8000/api/auth/user/';
const API_URL = 'http://127.0.0.1:8000/api/accounts/users/me/';
class UserService {
getPublicContent() {
return axios.get(API_URL + 'all');