Merge pull request #338 from ollama-webui/disable-signup

feat: toggle signup enable from admin panel
This commit is contained in:
Timothy Jaeryang Baek 2024-01-01 15:33:35 -05:00 committed by GitHub
commit fbd3854f8b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 169 additions and 28 deletions

View file

@ -22,7 +22,6 @@ ARG OLLAMA_API_BASE_URL='/ollama/api'
ENV ENV=prod ENV ENV=prod
ENV OLLAMA_API_BASE_URL $OLLAMA_API_BASE_URL ENV OLLAMA_API_BASE_URL $OLLAMA_API_BASE_URL
ENV WEBUI_AUTH ""
ENV WEBUI_JWT_SECRET_KEY "SECRET_KEY" ENV WEBUI_JWT_SECRET_KEY "SECRET_KEY"
WORKDIR /app WORKDIR /app

View file

@ -8,6 +8,8 @@ app = FastAPI()
origins = ["*"] origins = ["*"]
app.state.ENABLE_SIGNUP = True
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=origins, allow_origins=origins,

View file

@ -1,4 +1,4 @@
from fastapi import Response from fastapi import Response, Request
from fastapi import Depends, FastAPI, HTTPException, status from fastapi import Depends, FastAPI, HTTPException, status
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import List, Union from typing import List, Union
@ -93,7 +93,8 @@ async def signin(form_data: SigninForm):
@router.post("/signup", response_model=SigninResponse) @router.post("/signup", response_model=SigninResponse)
async def signup(form_data: SignupForm): async def signup(request: Request, form_data: SignupForm):
if request.app.state.ENABLE_SIGNUP:
if not Users.get_user_by_email(form_data.email.lower()): if not Users.get_user_by_email(form_data.email.lower()):
try: try:
role = "admin" if Users.get_num_users() == 0 else "pending" role = "admin" if Users.get_num_users() == 0 else "pending"
@ -121,3 +122,33 @@ async def signup(form_data: SignupForm):
raise HTTPException(500, detail=ERROR_MESSAGES.DEFAULT(err)) raise HTTPException(500, detail=ERROR_MESSAGES.DEFAULT(err))
else: else:
raise HTTPException(400, detail=ERROR_MESSAGES.EMAIL_TAKEN) raise HTTPException(400, detail=ERROR_MESSAGES.EMAIL_TAKEN)
else:
raise HTTPException(400, detail=ERROR_MESSAGES.ACCESS_PROHIBITED)
############################
# ToggleSignUp
############################
@router.get("/signup/enabled", response_model=bool)
async def get_sign_up_status(request: Request, user=Depends(get_current_user)):
if user.role == "admin":
return request.app.state.ENABLE_SIGNUP
else:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
)
@router.get("/signup/enabled/toggle", response_model=bool)
async def toggle_sign_up(request: Request, user=Depends(get_current_user)):
if user.role == "admin":
request.app.state.ENABLE_SIGNUP = not request.app.state.ENABLE_SIGNUP
return request.app.state.ENABLE_SIGNUP
else:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
)

View file

@ -15,6 +15,7 @@ from apps.web.models.auths import Auths
from utils.utils import get_current_user from utils.utils import get_current_user
from constants import ERROR_MESSAGES from constants import ERROR_MESSAGES
router = APIRouter() router = APIRouter()
############################ ############################

View file

@ -119,3 +119,57 @@ export const updateUserPassword = async (token: string, password: string, newPas
return res; return res;
}; };
export const getSignUpEnabledStatus = async (token: string) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/auths/signup/enabled`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
error = err.detail;
return null;
});
if (error) {
throw error;
}
return res;
};
export const toggleSignUpEnabledStatus = async (token: string) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/auths/signup/enabled/toggle`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
error = err.detail;
return null;
});
if (error) {
throw error;
}
return res;
};

View file

@ -7,10 +7,13 @@
import toast from 'svelte-french-toast'; import toast from 'svelte-french-toast';
import { updateUserRole, getUsers, deleteUserById } from '$lib/apis/users'; import { updateUserRole, getUsers, deleteUserById } from '$lib/apis/users';
import { getSignUpEnabledStatus, toggleSignUpEnabledStatus } from '$lib/apis/auths';
let loaded = false; let loaded = false;
let users = []; let users = [];
let signUpEnabled = true;
const updateRoleHandler = async (id, role) => { const updateRoleHandler = async (id, role) => {
const res = await updateUserRole(localStorage.token, id, role).catch((error) => { const res = await updateUserRole(localStorage.token, id, role).catch((error) => {
toast.error(error); toast.error(error);
@ -32,11 +35,17 @@
} }
}; };
const toggleSignUpEnabled = async () => {
signUpEnabled = await toggleSignUpEnabledStatus(localStorage.token);
};
onMount(async () => { onMount(async () => {
if ($user?.role !== 'admin') { if ($user?.role !== 'admin') {
await goto('/'); await goto('/');
} else { } else {
users = await getUsers(localStorage.token); users = await getUsers(localStorage.token);
signUpEnabled = await getSignUpEnabledStatus(localStorage.token);
} }
loaded = true; loaded = true;
}); });
@ -49,7 +58,52 @@
<div class="w-full max-w-3xl px-10 md:px-16 min-h-screen flex flex-col"> <div class="w-full max-w-3xl px-10 md:px-16 min-h-screen flex flex-col">
<div class="py-10 w-full"> <div class="py-10 w-full">
<div class=" flex flex-col justify-center"> <div class=" flex flex-col justify-center">
<div class=" flex justify-between items-center">
<div class=" text-2xl font-semibold">Users ({users.length})</div> <div class=" text-2xl font-semibold">Users ({users.length})</div>
<div>
<button
class="flex items-center space-x-1 border border-gray-200 px-3 py-1 rounded-lg"
type="button"
on:click={() => {
toggleSignUpEnabled();
}}
>
{#if signUpEnabled}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M11.5 1A3.5 3.5 0 0 0 8 4.5V7H2.5A1.5 1.5 0 0 0 1 8.5v5A1.5 1.5 0 0 0 2.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 9.5 7V4.5a2 2 0 1 1 4 0v1.75a.75.75 0 0 0 1.5 0V4.5A3.5 3.5 0 0 0 11.5 1Z"
/>
</svg>
<div class=" text-xs">
New Sign Up <span class=" font-semibold">Enabled</span>
</div>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M8 1a3.5 3.5 0 0 0-3.5 3.5V7A1.5 1.5 0 0 0 3 8.5v5A1.5 1.5 0 0 0 4.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 11.5 7V4.5A3.5 3.5 0 0 0 8 1Zm2 6V4.5a2 2 0 1 0-4 0V7h4Z"
clip-rule="evenodd"
/>
</svg>
<div class=" text-xs">
New Sign Up <span class=" font-semibold">Disabled</span>
</div>
{/if}
</button>
</div>
</div>
<div class=" text-gray-500 text-xs font-medium mt-1"> <div class=" text-gray-500 text-xs font-medium mt-1">
Click on the user role cell in the table to change a user's role. Click on the user role cell in the table to change a user's role.
</div> </div>