add register
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -7,7 +7,7 @@ from src.app.models.user import User, UserCreate
|
|||||||
from src.app.data.user import create_user, get_user_by_username
|
from src.app.data.user import create_user, get_user_by_username
|
||||||
|
|
||||||
from src.app.auth.dependancies import get_current_user, authenticate_user
|
from src.app.auth.dependancies import get_current_user, authenticate_user
|
||||||
from src.app.auth.security import hash_password, create_access_token
|
from src.app.auth.security import hash_password, create_access_token, verify_beyond_user_limit
|
||||||
from src.app.auth.schemas import Token
|
from src.app.auth.schemas import Token
|
||||||
|
|
||||||
router = APIRouter(prefix="/auth", tags=["auth"])
|
router = APIRouter(prefix="/auth", tags=["auth"])
|
||||||
@@ -30,12 +30,16 @@ async def user(current_user: Annotated[str, Depends(get_current_user)]):
|
|||||||
|
|
||||||
@router.post("/register")
|
@router.post("/register")
|
||||||
async def create(user_data: UserCreate):
|
async def create(user_data: UserCreate):
|
||||||
|
if(verify_beyond_user_limit()):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="The user limit has been reached."
|
||||||
|
)
|
||||||
if get_user_by_username(user_data.username):
|
if get_user_by_username(user_data.username):
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
detail="Username already registered"
|
detail="Username already registered"
|
||||||
)
|
)
|
||||||
|
|
||||||
hashed_password = hash_password(user_data.plain_password)
|
hashed_password = hash_password(user_data.plain_password)
|
||||||
user = User(username = user_data.username, hashed_password = hashed_password)
|
user = User(username = user_data.username, hashed_password = hashed_password)
|
||||||
created_user = create_user(user)
|
created_user = create_user(user)
|
||||||
|
|||||||
Binary file not shown.
@@ -1,5 +1,6 @@
|
|||||||
from src.app.config import settings
|
from src.app.config import settings
|
||||||
from typing import Optional
|
from typing import Optional, Sequence
|
||||||
|
from src.app.models.user import User
|
||||||
from datetime import timedelta, datetime, timezone
|
from datetime import timedelta, datetime, timezone
|
||||||
from argon2 import PasswordHasher
|
from argon2 import PasswordHasher
|
||||||
from argon2.exceptions import (
|
from argon2.exceptions import (
|
||||||
@@ -9,8 +10,7 @@ from argon2.exceptions import (
|
|||||||
)
|
)
|
||||||
import jwt
|
import jwt
|
||||||
from jwt.exceptions import InvalidTokenError
|
from jwt.exceptions import InvalidTokenError
|
||||||
|
from src.app.data.user import get_users
|
||||||
|
|
||||||
|
|
||||||
password_hasher = PasswordHasher()
|
password_hasher = PasswordHasher()
|
||||||
|
|
||||||
@@ -37,4 +37,11 @@ def verify_token(token: str, token_type: str = "access") -> Optional[dict]:
|
|||||||
except InvalidTokenError:
|
except InvalidTokenError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def verify_beyond_user_limit() -> bool:
|
||||||
|
users: Sequence[User] = get_users()
|
||||||
|
if (len(users) > settings.USER_LIMIT):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
#def create_refresh_token(data: dict) -> str:
|
#def create_refresh_token(data: dict) -> str:
|
||||||
@@ -14,6 +14,7 @@ class Settings(BaseSettings):
|
|||||||
SECRET_KEY : str = Field('random_string', env='SECRET_KEY')
|
SECRET_KEY : str = Field('random_string', env='SECRET_KEY')
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = 240
|
ACCESS_TOKEN_EXPIRE_MINUTES: int = 240
|
||||||
ALGORITHM: str = "HS256"
|
ALGORITHM: str = "HS256"
|
||||||
|
USER_LIMIT: int = 10
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
env_file = ".env"
|
env_file = ".env"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import { isAuthenticated } from '@/services/apiAxios'
|
import { isAuthenticated } from '@/services/apiAxios'
|
||||||
|
|
||||||
const pagesWithoutGuard = ['login', 'app']
|
const pagesWithoutGuard = ['login', 'app', 'register']
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@@ -22,14 +22,20 @@ const router = createRouter({
|
|||||||
path: '/login',
|
path: '/login',
|
||||||
alias: '/login',
|
alias: '/login',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
component: () => import('@/views/AuthView.vue'),
|
component: () => import('@/views/LoginView.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/register',
|
||||||
|
alias: '/register',
|
||||||
|
name: 'register',
|
||||||
|
component: () => import('@/views/RegisterView.vue'),
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
router.beforeEach(async (to, from) => {
|
router.beforeEach(async (to, from) => {
|
||||||
const isAuth = await isAuthenticated()
|
const isAuth = await isAuthenticated()
|
||||||
if (!isAuth && !pagesWithoutGuard.includes(to.name!.toString())) {
|
if (!isAuth && pagesWithoutGuard.includes(to.name!.toString())) {
|
||||||
return { name: 'login' }
|
return { name: 'login' }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ api.interceptors.request.use((config) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const authAPI = {
|
export const authAPI = {
|
||||||
register: (data: unknown) => api.post('/api/v1/auth/register', data),
|
register: (username: string, password: string) =>
|
||||||
|
api.post(
|
||||||
|
'/api/v1/auth/register',
|
||||||
|
{ "username":username, "plain_password":password }
|
||||||
|
),
|
||||||
login: (username: string, password: string) =>
|
login: (username: string, password: string) =>
|
||||||
api.post(
|
api.post(
|
||||||
'/api/v1/auth/login',
|
'/api/v1/auth/login',
|
||||||
|
|||||||
63
user-interface/src/views/RegisterView.vue
Normal file
63
user-interface/src/views/RegisterView.vue
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import router from '@/router/index'
|
||||||
|
import { BField, BInput, BButton, useToast } from "buefy";
|
||||||
|
import { ref } from "vue"
|
||||||
|
import { authAPI } from '@/services/apiAxios'
|
||||||
|
|
||||||
|
const username = ref<string>("")
|
||||||
|
const password = ref<string>("")
|
||||||
|
|
||||||
|
const Toast = useToast()
|
||||||
|
|
||||||
|
async function register() {
|
||||||
|
try {
|
||||||
|
const responseRegister = await authAPI.register(username.value, password.value)
|
||||||
|
if(responseRegister.status != 200)
|
||||||
|
throw new Error("Registred failed")
|
||||||
|
const responseLogin = await authAPI.login(username.value, password.value)
|
||||||
|
const { access_token, refresh_token } = responseLogin.data
|
||||||
|
|
||||||
|
localStorage.setItem('access_token', access_token)
|
||||||
|
localStorage.setItem('refresh_token', refresh_token)
|
||||||
|
|
||||||
|
router.push({ path: '/experiment' })
|
||||||
|
} catch (err){
|
||||||
|
console.log(err)
|
||||||
|
Toast.open({message: "Registred failed", type: "is-danger"})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<b-field label="Username">
|
||||||
|
<!-- @vue-ignore -->
|
||||||
|
<b-input
|
||||||
|
v-model="username"
|
||||||
|
placeholder="Alice"
|
||||||
|
maxlength="20"
|
||||||
|
required
|
||||||
|
></b-input>
|
||||||
|
</b-field>
|
||||||
|
<b-field label="Password">
|
||||||
|
<!-- @vue-ignore -->
|
||||||
|
<b-input
|
||||||
|
v-model="password"
|
||||||
|
maxlength="50"
|
||||||
|
type="password"
|
||||||
|
required
|
||||||
|
></b-input>
|
||||||
|
</b-field>
|
||||||
|
<b-button type="is-primary" @click="register">Register</b-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container{
|
||||||
|
width: 20%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 34px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user