add register

This commit is contained in:
Robin COuret
2026-03-06 19:35:28 +01:00
parent 34845b9696
commit ed0d989915
10 changed files with 95 additions and 10 deletions

View File

@@ -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)

View File

@@ -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:

View File

@@ -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"

View File

@@ -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' }
} }
}) })

View File

@@ -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',

View File

@@ -46,7 +46,7 @@
required required
></b-input> ></b-input>
</b-field> </b-field>
<b-button type="is-primary" @click="login" >Login</b-button> <b-button type="is-primary" @click="login">Login</b-button>
</div> </div>
</template> </template>

View 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>