feat: enhance admin setup with email validation and update workflows for fresh lib cloning
parent
290b149855
commit
41d8e25843
|
|
@ -13,14 +13,21 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
# Do NOT use submodules: recursive — the submodule pointers in this repo
|
||||
# are stale and predate package.json. We clone the libs fresh below.
|
||||
|
||||
- name: Setup Node.js 22
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
# Clone wokwi-libs fresh (stale submodule pointers can't be used)
|
||||
- name: Clone wokwi-libs
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/wokwi/avr8js.git wokwi-libs/avr8js
|
||||
git clone --depth=1 https://github.com/wokwi/rp2040js.git wokwi-libs/rp2040js
|
||||
git clone --depth=1 https://github.com/wokwi/wokwi-elements.git wokwi-libs/wokwi-elements
|
||||
|
||||
# Cache wokwi-libs node_modules to speed up repeated runs
|
||||
- name: Cache wokwi-libs node_modules
|
||||
uses: actions/cache@v4
|
||||
|
|
|
|||
|
|
@ -46,20 +46,14 @@ async def setup_admin(body: AdminSetupRequest, db: AsyncSession = Depends(get_db
|
|||
|
||||
# Check uniqueness
|
||||
conflict = await db.execute(
|
||||
select(User).where(User.username == username)
|
||||
select(User).where((User.username == username) | (User.email == body.email))
|
||||
)
|
||||
if conflict.scalar_one_or_none():
|
||||
raise HTTPException(status_code=400, detail="Username already taken.")
|
||||
|
||||
# Generate a placeholder email for the admin setup account
|
||||
email = f"{username}@admin.local"
|
||||
email_conflict = await db.execute(select(User).where(User.email == email))
|
||||
if email_conflict.scalar_one_or_none():
|
||||
email = f"{username}.admin@admin.local"
|
||||
raise HTTPException(status_code=400, detail="Username or email already taken.")
|
||||
|
||||
user = User(
|
||||
username=username,
|
||||
email=email,
|
||||
email=body.email,
|
||||
hashed_password=hash_password(body.password),
|
||||
is_admin=True,
|
||||
is_active=True,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from pydantic import BaseModel, EmailStr
|
|||
|
||||
class AdminSetupRequest(BaseModel):
|
||||
username: str
|
||||
email: EmailStr
|
||||
password: str
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ const modalStyles: Record<string, React.CSSProperties> = {
|
|||
|
||||
function SetupScreen({ onDone }: { onDone: () => void }) {
|
||||
const [username, setUsername] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [confirm, setConfirm] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
|
|
@ -157,7 +158,7 @@ function SetupScreen({ onDone }: { onDone: () => void }) {
|
|||
}
|
||||
setLoading(true);
|
||||
try {
|
||||
await createFirstAdmin(username, password);
|
||||
await createFirstAdmin(username, email, password);
|
||||
onDone();
|
||||
navigate('/login?redirect=/admin');
|
||||
} catch (err: any) {
|
||||
|
|
@ -183,6 +184,15 @@ function SetupScreen({ onDone }: { onDone: () => void }) {
|
|||
autoFocus
|
||||
placeholder="admin"
|
||||
/>
|
||||
<label style={s.label}>Email</label>
|
||||
<input
|
||||
style={s.input}
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
placeholder="admin@example.com"
|
||||
/>
|
||||
<label style={s.label}>Password</label>
|
||||
<input
|
||||
style={s.input}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ export async function getAdminSetupStatus(): Promise<{ has_admin: boolean }> {
|
|||
return data;
|
||||
}
|
||||
|
||||
export async function createFirstAdmin(username: string, password: string): Promise<AdminUserResponse> {
|
||||
const { data } = await api.post('/admin/setup', { username, password });
|
||||
export async function createFirstAdmin(username: string, email: string, password: string): Promise<AdminUserResponse> {
|
||||
const { data } = await api.post('/admin/setup', { username, email, password });
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue