gitscope
https://dev.kronoz.win/r/marzneshin.git
app/routes/admin.py · v0.5.5
Source
1 d4ec019 Dawsh 2y ago from typing import Optional, Annotated
2 a47eb4c Dawsh 2y ago
3 a47eb4c Dawsh 2y ago import sqlalchemy
4 f7af2b3 Dawsh 2y ago from fastapi import APIRouter
5 f7af2b3 Dawsh 2y ago from fastapi import Depends, HTTPException, status
6 f7af2b3 Dawsh 2y ago from fastapi.security import OAuth2PasswordRequestForm
7 d4ec019 Dawsh 2y ago from fastapi_pagination import Page
8 d4ec019 Dawsh 2y ago from fastapi_pagination.ext.sqlalchemy import paginate
9 f7af2b3 Dawsh 2y ago
10 c13a1aa Dawsh 2y ago from app.db import Session, crud
11 4708fcb Dawsh 2y ago from app.db.models import Admin as DBAdmin, Service, User
12 f7af2b3 Dawsh 2y ago from app.dependencies import AdminDep, SudoAdminDep, DBDep
13 4708fcb Dawsh 2y ago from app.marznode.operations import update_user
14 4708fcb Dawsh 2y ago from app.models.admin import (
15 4708fcb Dawsh 2y ago Admin,
16 4708fcb Dawsh 2y ago AdminCreate,
17 4708fcb Dawsh 2y ago AdminInDB,
18 4708fcb Dawsh 2y ago Token,
19 4708fcb Dawsh 2y ago AdminPartialModify,
20 4708fcb Dawsh 2y ago AdminResponse,
21 4708fcb Dawsh 2y ago )
22 4708fcb Dawsh 2y ago from app.models.service import ServiceResponse
23 4708fcb Dawsh 2y ago from app.models.user import UserResponse
24 e652421 Dawsh 2y ago from app.utils.auth import create_admin_token
25 f7af2b3 Dawsh 2y ago
26 5bb2712 Mardin 2y ago router = APIRouter(tags=["Admin"], prefix="/admins")
27 a47eb4c Dawsh 2y ago
28 a47eb4c Dawsh 2y ago
29 f1ab16c Dawsh 2y ago def authenticate_admin(
30 f1ab16c Dawsh 2y ago db: Session, username: str, password: str
31 f1ab16c Dawsh 2y ago ) -> Optional[Admin]:
32 a47eb4c Dawsh 2y ago dbadmin = crud.get_admin(db, username)
33 a47eb4c Dawsh 2y ago if not dbadmin:
34 a47eb4c Dawsh 2y ago return None
35 a47eb4c Dawsh 2y ago
36 01cdf2e Dawsh 2y ago return (
37 f1ab16c Dawsh 2y ago dbadmin
38 f1ab16c Dawsh 2y ago if AdminInDB.model_validate(dbadmin).verify_password(password)
39 f1ab16c Dawsh 2y ago else None
40 01cdf2e Dawsh 2y ago )
41 a47eb4c Dawsh 2y ago
42 a47eb4c Dawsh 2y ago
43 4708fcb Dawsh 2y ago @router.get("", response_model=Page[AdminResponse])
44 f4fecee Dawsh 2y ago def get_admins(db: DBDep, admin: SudoAdminDep, username: str | None = None):
45 d4ec019 Dawsh 2y ago query = db.query(DBAdmin)
46 d4ec019 Dawsh 2y ago if username:
47 01cdf2e Dawsh 2y ago query = query.filter(DBAdmin.username.ilike(f"%{username}%"))
48 d4ec019 Dawsh 2y ago return paginate(db, query)
49 d4ec019 Dawsh 2y ago
50 d4ec019 Dawsh 2y ago
51 d4ec019 Dawsh 2y ago @router.post("", response_model=Admin)
52 01cdf2e Dawsh 2y ago def create_admin(new_admin: AdminCreate, db: DBDep, admin: SudoAdminDep):
53 d4ec019 Dawsh 2y ago try:
54 d4ec019 Dawsh 2y ago dbadmin = crud.create_admin(db, new_admin)
55 d4ec019 Dawsh 2y ago except sqlalchemy.exc.IntegrityError:
56 d4ec019 Dawsh 2y ago db.rollback()
57 d4ec019 Dawsh 2y ago raise HTTPException(status_code=409, detail="Admin already exists")
58 d4ec019 Dawsh 2y ago
59 d4ec019 Dawsh 2y ago return dbadmin
60 d4ec019 Dawsh 2y ago
61 d4ec019 Dawsh 2y ago
62 d4ec019 Dawsh 2y ago @router.get("/current", response_model=Admin)
63 d4ec019 Dawsh 2y ago def get_current_admin(admin: AdminDep):
64 d4ec019 Dawsh 2y ago return admin
65 d4ec019 Dawsh 2y ago
66 d4ec019 Dawsh 2y ago
67 2de9d72 Dawsh 2y ago @router.post("/token", response_model=Token)
68 f1ab16c Dawsh 2y ago def admin_token(
69 f1ab16c Dawsh 2y ago form_data: Annotated[OAuth2PasswordRequestForm, Depends()], db: DBDep
70 f1ab16c Dawsh 2y ago ):
71 f1ab16c Dawsh 2y ago if dbadmin := authenticate_admin(
72 f1ab16c Dawsh 2y ago db, form_data.username, form_data.password
73 f1ab16c Dawsh 2y ago ):
74 01cdf2e Dawsh 2y ago return Token(
75 9ddfbc8 Mardin 2y ago is_sudo=dbadmin.is_sudo,
76 f1ab16c Dawsh 2y ago access_token=create_admin_token(
77 f1ab16c Dawsh 2y ago form_data.username, is_sudo=dbadmin.is_sudo
78 9ddfbc8 Mardin 2y ago ),
79 01cdf2e Dawsh 2y ago )
80 a47eb4c Dawsh 2y ago
81 a47eb4c Dawsh 2y ago raise HTTPException(
82 a47eb4c Dawsh 2y ago status_code=status.HTTP_401_UNAUTHORIZED,
83 a47eb4c Dawsh 2y ago detail="Incorrect username or password",
84 a47eb4c Dawsh 2y ago headers={"WWW-Authenticate": "Bearer"},
85 a47eb4c Dawsh 2y ago )
86 a47eb4c Dawsh 2y ago
87 a47eb4c Dawsh 2y ago
88 4708fcb Dawsh 2y ago @router.get("/{username}", response_model=AdminResponse)
89 4708fcb Dawsh 2y ago def get_admin(
90 4708fcb Dawsh 2y ago username: str,
91 4708fcb Dawsh 2y ago db: DBDep,
92 4708fcb Dawsh 2y ago admin: SudoAdminDep,
93 01cdf2e Dawsh 2y ago ):
94 4708fcb Dawsh 2y ago return crud.get_admin(db, username)
95 a47eb4c Dawsh 2y ago
96 a47eb4c Dawsh 2y ago
97 4708fcb Dawsh 2y ago @router.put("/{username}", response_model=AdminResponse)
98 4708fcb Dawsh 2y ago def modify_admin(
99 4708fcb Dawsh 2y ago username: str,
100 4708fcb Dawsh 2y ago modified_admin: AdminPartialModify,
101 4708fcb Dawsh 2y ago db: DBDep,
102 4708fcb Dawsh 2y ago admin: SudoAdminDep,
103 4708fcb Dawsh 2y ago ):
104 a47eb4c Dawsh 2y ago dbadmin = crud.get_admin(db, username)
105 a47eb4c Dawsh 2y ago if not dbadmin:
106 a47eb4c Dawsh 2y ago raise HTTPException(status_code=404, detail="Admin not found")
107 a47eb4c Dawsh 2y ago
108 a47eb4c Dawsh 2y ago # If a sudoer admin wants to edit another sudoer
109 f4fecee Dawsh 2y ago if username != admin.username and dbadmin.is_sudo:
110 a47eb4c Dawsh 2y ago raise HTTPException(
111 a47eb4c Dawsh 2y ago status_code=403,
112 f4fecee Dawsh 2y ago detail="You're not allowed to edit another sudoers account. Use marzneshin-cli instead.",
113 a47eb4c Dawsh 2y ago )
114 a47eb4c Dawsh 2y ago
115 a47eb4c Dawsh 2y ago dbadmin = crud.update_admin(db, dbadmin, modified_admin)
116 a47eb4c Dawsh 2y ago return dbadmin
117 a47eb4c Dawsh 2y ago
118 a47eb4c Dawsh 2y ago
119 4708fcb Dawsh 2y ago @router.get("/{username}/services", response_model=Page[ServiceResponse])
120 4708fcb Dawsh 2y ago def get_admin_services(username: str, db: DBDep, admin: SudoAdminDep):
121 4708fcb Dawsh 2y ago """
122 4708fcb Dawsh 2y ago Get user services
123 4708fcb Dawsh 2y ago """
124 4708fcb Dawsh 2y ago db_admin = crud.get_admin(db, username)
125 4708fcb Dawsh 2y ago if not db_admin:
126 4708fcb Dawsh 2y ago raise HTTPException(status_code=404, detail="Admin not found")
127 4708fcb Dawsh 2y ago
128 4708fcb Dawsh 2y ago if db_admin.is_sudo or db_admin.all_services_access:
129 4708fcb Dawsh 2y ago query = db.query(Service)
130 4708fcb Dawsh 2y ago else:
131 4708fcb Dawsh 2y ago query = (
132 4708fcb Dawsh 2y ago db.query(Service)
133 4708fcb Dawsh 2y ago .join(Service.admins)
134 4708fcb Dawsh 2y ago .where(DBAdmin.id == db_admin.id)
135 4708fcb Dawsh 2y ago )
136 4708fcb Dawsh 2y ago
137 4708fcb Dawsh 2y ago return paginate(query)
138 4708fcb Dawsh 2y ago
139 4708fcb Dawsh 2y ago
140 4708fcb Dawsh 2y ago @router.get("/{username}/users", response_model=Page[UserResponse])
141 4708fcb Dawsh 2y ago def get_admin_users(username: str, db: DBDep, admin: SudoAdminDep):
142 4708fcb Dawsh 2y ago """
143 4708fcb Dawsh 2y ago Get user services
144 4708fcb Dawsh 2y ago """
145 4708fcb Dawsh 2y ago db_admin = crud.get_admin(db, username)
146 4708fcb Dawsh 2y ago if not db_admin:
147 4708fcb Dawsh 2y ago raise HTTPException(status_code=404, detail="Admin not found")
148 4708fcb Dawsh 2y ago
149 4708fcb Dawsh 2y ago query = db.query(User).where(User.admin_id == db_admin.id)
150 4708fcb Dawsh 2y ago
151 4708fcb Dawsh 2y ago return paginate(query)
152 4708fcb Dawsh 2y ago
153 4708fcb Dawsh 2y ago
154 4708fcb Dawsh 2y ago @router.get("/{username}/disable_users", response_model=AdminResponse)
155 4708fcb Dawsh 2y ago async def disable_users(username: str, db: DBDep, admin: SudoAdminDep):
156 4708fcb Dawsh 2y ago db_admin = crud.get_admin(db, username)
157 4708fcb Dawsh 2y ago if not db_admin:
158 4708fcb Dawsh 2y ago raise HTTPException(status_code=404, detail="Admin not found")
159 4708fcb Dawsh 2y ago
160 4708fcb Dawsh 2y ago if db_admin.is_sudo and db_admin.username != admin.username:
161 4708fcb Dawsh 2y ago raise HTTPException(
162 4708fcb Dawsh 2y ago status_code=403,
163 4708fcb Dawsh 2y ago detail="You're not allowed.",
164 4708fcb Dawsh 2y ago )
165 4708fcb Dawsh 2y ago
166 4708fcb Dawsh 2y ago for user in crud.get_users(db, admin=db_admin, enabled=True):
167 4708fcb Dawsh 2y ago if user.activated:
168 4708fcb Dawsh 2y ago update_user(user, remove=True)
169 4708fcb Dawsh 2y ago user.enabled = False
170 4708fcb Dawsh 2y ago user.activated = False
171 4708fcb Dawsh 2y ago db.commit()
172 4708fcb Dawsh 2y ago
173 4708fcb Dawsh 2y ago return db_admin
174 4708fcb Dawsh 2y ago
175 4708fcb Dawsh 2y ago
176 4708fcb Dawsh 2y ago @router.get("/{username}/enable_users", response_model=AdminResponse)
177 4708fcb Dawsh 2y ago async def enable_users(username: str, db: DBDep, admin: SudoAdminDep):
178 4708fcb Dawsh 2y ago db_admin = crud.get_admin(db, username)
179 4708fcb Dawsh 2y ago if not db_admin:
180 4708fcb Dawsh 2y ago raise HTTPException(status_code=404, detail="Admin not found")
181 4708fcb Dawsh 2y ago
182 4708fcb Dawsh 2y ago if db_admin.is_sudo and db_admin.username != admin.username:
183 4708fcb Dawsh 2y ago raise HTTPException(
184 4708fcb Dawsh 2y ago status_code=403,
185 4708fcb Dawsh 2y ago detail="You're not allowed.",
186 4708fcb Dawsh 2y ago )
187 4708fcb Dawsh 2y ago
188 4708fcb Dawsh 2y ago for user in crud.get_users(db, admin=db_admin, enabled=False):
189 4708fcb Dawsh 2y ago user.enabled = True
190 4708fcb Dawsh 2y ago if user.is_active:
191 4708fcb Dawsh 2y ago update_user(user)
192 4708fcb Dawsh 2y ago user.activated = True
193 4708fcb Dawsh 2y ago db.commit()
194 4708fcb Dawsh 2y ago
195 4708fcb Dawsh 2y ago return db_admin
196 4708fcb Dawsh 2y ago
197 4708fcb Dawsh 2y ago
198 2de9d72 Dawsh 2y ago @router.delete("/{username}")
199 01cdf2e Dawsh 2y ago def remove_admin(username: str, db: DBDep, admin: SudoAdminDep):
200 a47eb4c Dawsh 2y ago dbadmin = crud.get_admin(db, username)
201 a47eb4c Dawsh 2y ago if not dbadmin:
202 a47eb4c Dawsh 2y ago raise HTTPException(status_code=404, detail="Admin not found")
203 a47eb4c Dawsh 2y ago
204 f9bc14b Dawsh 2y ago if dbadmin.is_sudo:
205 a47eb4c Dawsh 2y ago raise HTTPException(
206 a47eb4c Dawsh 2y ago status_code=403,
207 f4fecee Dawsh 2y ago detail="You're not allowed to delete sudoers accounts. Use marzneshin-cli instead.",
208 a47eb4c Dawsh 2y ago )
209 a47eb4c Dawsh 2y ago
210 c13a1aa Dawsh 2y ago crud.remove_admin(db, dbadmin)
211 a47eb4c Dawsh 2y ago return {}