mirror of
https://github.com/mudler/LocalAI.git
synced 2026-03-31 13:15:51 -04:00
fix(auth): do not allow to register in invite mode (#9101)
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
committed by
GitHub
parent
5d410e5a03
commit
15935e9d5f
@@ -213,6 +213,22 @@ func (m *OAuthManager) CallbackHandler(providerName string, db *gorm.DB, adminEm
|
||||
})
|
||||
}
|
||||
|
||||
// In invite mode, block new OAuth users who don't have a valid invite code
|
||||
// to prevent phantom pending records from accumulating in the DB.
|
||||
// The first user (no users in DB yet) is always allowed through.
|
||||
if registrationMode == "invite" && inviteCode == "" {
|
||||
var existing User
|
||||
if err := db.Where("provider = ? AND subject = ?", providerName, userInfo.Subject).First(&existing).Error; err != nil {
|
||||
// Check if this would be the first user (always allowed)
|
||||
var userCount int64
|
||||
db.Model(&User{}).Count(&userCount)
|
||||
if userCount > 0 {
|
||||
// New user without invite code — reject without creating a DB record
|
||||
return c.Redirect(http.StatusTemporaryRedirect, "/login?error=invite_required")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Upsert user (with invite code support)
|
||||
user, err := upsertOAuthUser(db, providerName, userInfo, adminEmail, registrationMode)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
|
||||
import { useAuth } from '../context/AuthContext'
|
||||
import { apiUrl } from '../utils/basePath'
|
||||
import './auth.css'
|
||||
@@ -7,6 +7,7 @@ import './auth.css'
|
||||
export default function Login() {
|
||||
const navigate = useNavigate()
|
||||
const { code: urlInviteCode } = useParams()
|
||||
const [searchParams] = useSearchParams()
|
||||
const { authEnabled, user, loading: authLoading, refresh } = useAuth()
|
||||
const [providers, setProviders] = useState([])
|
||||
const [hasUsers, setHasUsers] = useState(true)
|
||||
@@ -42,6 +43,14 @@ export default function Login() {
|
||||
}
|
||||
}, [urlInviteCode])
|
||||
|
||||
// Show error from OAuth redirect (e.g. invite_required)
|
||||
useEffect(() => {
|
||||
const errorParam = searchParams.get('error')
|
||||
if (errorParam === 'invite_required') {
|
||||
setError('A valid invite code is required to register')
|
||||
}
|
||||
}, [searchParams])
|
||||
|
||||
useEffect(() => {
|
||||
fetch(apiUrl('/api/auth/status'))
|
||||
.then(r => r.json())
|
||||
@@ -252,12 +261,14 @@ export default function Login() {
|
||||
<button type="submit" className="btn btn-primary login-btn-full" disabled={submitting}>
|
||||
{submitting ? 'Signing in...' : 'Sign In'}
|
||||
</button>
|
||||
<p className="login-footer">
|
||||
Don't have an account?{' '}
|
||||
<button type="button" className="login-link" onClick={() => { setMode('register'); setError(''); setMessage('') }}>
|
||||
Register
|
||||
</button>
|
||||
</p>
|
||||
{!(registrationMode === 'invite' && hasUsers && !urlInviteCode) && (
|
||||
<p className="login-footer">
|
||||
Don't have an account?{' '}
|
||||
<button type="button" className="login-link" onClick={() => { setMode('register'); setError(''); setMessage('') }}>
|
||||
Register
|
||||
</button>
|
||||
</p>
|
||||
)}
|
||||
</form>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user