gitscope
https://dev.kronoz.win/r/marzneshin.git
app/db/crud.py · v0.6.2
Source
1 12b255b Dawsh 2y ago import json
2 34a7612 Dawsh 2y ago import secrets
3 e6e6467 Dawsh 2y ago from collections import defaultdict
4 e6e6467 Dawsh 2y ago from datetime import datetime, timedelta, timezone
5 a47eb4c Dawsh 2y ago from enum import Enum
6 4708fcb Dawsh 2y ago from types import NoneType
7 2de9d72 Dawsh 2y ago from typing import List, Optional, Tuple, Union
8 a47eb4c Dawsh 2y ago
9 9ca312d Dawsh 2y ago from sqlalchemy import and_, delete, update, select, func, cast, Date
10 a47eb4c Dawsh 2y ago from sqlalchemy.orm import Session
11 a47eb4c Dawsh 2y ago
12 01cdf2e Dawsh 2y ago from app.db.models import (
13 01cdf2e Dawsh 2y ago JWT,
14 01cdf2e Dawsh 2y ago TLS,
15 01cdf2e Dawsh 2y ago Admin,
16 01cdf2e Dawsh 2y ago Node,
17 01cdf2e Dawsh 2y ago NodeUserUsage,
18 01cdf2e Dawsh 2y ago NotificationReminder,
19 01cdf2e Dawsh 2y ago InboundHost,
20 01cdf2e Dawsh 2y ago Service,
21 01cdf2e Dawsh 2y ago Inbound,
22 01cdf2e Dawsh 2y ago System,
23 01cdf2e Dawsh 2y ago User,
24 f5c168d Mardin 2y ago Backend,
25 01cdf2e Dawsh 2y ago )
26 4708fcb Dawsh 2y ago from app.models.admin import AdminCreate, AdminPartialModify
27 f1ab16c Dawsh 2y ago from app.models.node import (
28 f1ab16c Dawsh 2y ago NodeCreate,
29 f1ab16c Dawsh 2y ago NodeModify,
30 f1ab16c Dawsh 2y ago NodeStatus,
31 f1ab16c Dawsh 2y ago )
32 a47eb4c Dawsh 2y ago from app.models.proxy import InboundHost as InboundHostModify
33 2de9d72 Dawsh 2y ago from app.models.service import Service as ServiceModify, ServiceCreate
34 6a4fee1 Dawsh 2y ago from app.models.system import TrafficUsageSeries
35 01cdf2e Dawsh 2y ago from app.models.user import (
36 01cdf2e Dawsh 2y ago ReminderType,
37 01cdf2e Dawsh 2y ago UserCreate,
38 d377c4c Dawsh 2y ago UserDataUsageResetStrategy,
39 01cdf2e Dawsh 2y ago UserModify,
40 01cdf2e Dawsh 2y ago UserStatus,
41 d377c4c Dawsh 2y ago UserExpireStrategy,
42 e6e6467 Dawsh 2y ago UserNodeUsageSeries,
43 e6e6467 Dawsh 2y ago UserUsageSeriesResponse,
44 f1ab16c Dawsh 2y ago )
45 a47eb4c Dawsh 2y ago
46 a47eb4c Dawsh 2y ago
47 a47eb4c Dawsh 2y ago def add_default_hosts(db: Session, inbounds: List[Inbound]):
48 01cdf2e Dawsh 2y ago hosts = [
49 01cdf2e Dawsh 2y ago InboundHost(
50 01cdf2e Dawsh 2y ago remark="🚀 Marz ({USERNAME}) [{PROTOCOL} - {TRANSPORT}]",
51 01cdf2e Dawsh 2y ago address="{SERVER_IP}",
52 01cdf2e Dawsh 2y ago inbound=i,
53 01cdf2e Dawsh 2y ago )
54 01cdf2e Dawsh 2y ago for i in inbounds
55 01cdf2e Dawsh 2y ago ]
56 a47eb4c Dawsh 2y ago db.add_all(hosts)
57 a47eb4c Dawsh 2y ago db.commit()
58 a47eb4c Dawsh 2y ago
59 a47eb4c Dawsh 2y ago
60 f5c168d Mardin 2y ago def ensure_node_backends(db: Session, backends, node_id: int):
61 f5c168d Mardin 2y ago old_backends = db.query(Backend).where(Backend.node_id == node_id)
62 f5c168d Mardin 2y ago for backend in old_backends:
63 f5c168d Mardin 2y ago db.delete(backend)
64 f5c168d Mardin 2y ago backends = [
65 f5c168d Mardin 2y ago Backend(
66 f5c168d Mardin 2y ago name=backend.name,
67 f5c168d Mardin 2y ago backend_type=backend.type,
68 f5c168d Mardin 2y ago version=backend.version,
69 f5c168d Mardin 2y ago node_id=node_id,
70 f5c168d Mardin 2y ago )
71 f5c168d Mardin 2y ago for backend in backends
72 f5c168d Mardin 2y ago ]
73 f5c168d Mardin 2y ago db.add_all(backends)
74 f5c168d Mardin 2y ago db.flush()
75 f5c168d Mardin 2y ago
76 f5c168d Mardin 2y ago
77 f5c168d Mardin 2y ago def ensure_node_inbounds(db: Session, inbounds: List[Inbound], node_id: int):
78 01cdf2e Dawsh 2y ago current_tags = [
79 01cdf2e Dawsh 2y ago i[0]
80 01cdf2e Dawsh 2y ago for i in db.execute(
81 01cdf2e Dawsh 2y ago select(Inbound.tag).filter(Inbound.node_id == node_id)
82 01cdf2e Dawsh 2y ago ).all()
83 01cdf2e Dawsh 2y ago ]
84 512d183 Mrdn 2y ago updated_tags = set(i.tag for i in list(inbounds))
85 512d183 Mrdn 2y ago inbound_additions, tag_deletions = list(), set()
86 512d183 Mrdn 2y ago for tag in current_tags:
87 512d183 Mrdn 2y ago if tag not in updated_tags:
88 512d183 Mrdn 2y ago tag_deletions.add(tag)
89 f5c168d Mardin 2y ago removals = db.query(Inbound).where(
90 01cdf2e Dawsh 2y ago and_(Inbound.node_id == node_id, Inbound.tag.in_(tag_deletions))
91 01cdf2e Dawsh 2y ago )
92 f5c168d Mardin 2y ago for i in removals:
93 512d183 Mrdn 2y ago db.delete(i)
94 512d183 Mrdn 2y ago
95 512d183 Mrdn 2y ago for inb in inbounds:
96 512d183 Mrdn 2y ago if inb.tag in current_tags:
97 01cdf2e Dawsh 2y ago stmt = (
98 01cdf2e Dawsh 2y ago update(Inbound)
99 f1ab16c Dawsh 2y ago .where(
100 f1ab16c Dawsh 2y ago and_(Inbound.node_id == node_id, Inbound.tag == inb.tag)
101 f1ab16c Dawsh 2y ago )
102 f1ab16c Dawsh 2y ago .values(
103 f1ab16c Dawsh 2y ago protocol=json.loads(inb.config)["protocol"],
104 f1ab16c Dawsh 2y ago config=inb.config,
105 f1ab16c Dawsh 2y ago )
106 a47eb4c Dawsh 2y ago )
107 512d183 Mrdn 2y ago db.execute(stmt)
108 512d183 Mrdn 2y ago else:
109 512d183 Mrdn 2y ago inbound_additions.append(inb)
110 01cdf2e Dawsh 2y ago new_inbounds = [
111 01cdf2e Dawsh 2y ago Inbound(
112 01cdf2e Dawsh 2y ago tag=inb.tag,
113 01cdf2e Dawsh 2y ago protocol=json.loads(inb.config)["protocol"],
114 01cdf2e Dawsh 2y ago config=inb.config,
115 01cdf2e Dawsh 2y ago node_id=node_id,
116 01cdf2e Dawsh 2y ago )
117 01cdf2e Dawsh 2y ago for inb in inbound_additions
118 01cdf2e Dawsh 2y ago ]
119 a47eb4c Dawsh 2y ago db.add_all(new_inbounds)
120 a47eb4c Dawsh 2y ago db.flush()
121 a47eb4c Dawsh 2y ago for i in new_inbounds:
122 2de9d72 Dawsh 2y ago db.refresh(i)
123 a47eb4c Dawsh 2y ago add_default_hosts(db, new_inbounds)
124 a47eb4c Dawsh 2y ago db.commit()
125 a47eb4c Dawsh 2y ago
126 a47eb4c Dawsh 2y ago
127 01cdf2e Dawsh 2y ago def get_node_users(
128 f1ab16c Dawsh 2y ago db: Session,
129 d377c4c Dawsh 2y ago node_id: int,
130 01cdf2e Dawsh 2y ago ):
131 01cdf2e Dawsh 2y ago query = (
132 01cdf2e Dawsh 2y ago db.query(User.id, User.username, User.key, Inbound)
133 01cdf2e Dawsh 2y ago .distinct()
134 01cdf2e Dawsh 2y ago .join(Inbound.services)
135 01cdf2e Dawsh 2y ago .join(Service.users)
136 01cdf2e Dawsh 2y ago .filter(Inbound.node_id == node_id)
137 d377c4c Dawsh 2y ago .filter(User.activated == True)
138 01cdf2e Dawsh 2y ago )
139 a47eb4c Dawsh 2y ago return query.all()
140 a47eb4c Dawsh 2y ago
141 12b255b Dawsh 2y ago
142 a47eb4c Dawsh 2y ago def get_user_hosts(db: Session, user_id: int):
143 01cdf2e Dawsh 2y ago return (
144 01cdf2e Dawsh 2y ago db.query(InboundHost)
145 01cdf2e Dawsh 2y ago .distinct()
146 01cdf2e Dawsh 2y ago .join(User.services)
147 01cdf2e Dawsh 2y ago .join(Service.inbounds)
148 01cdf2e Dawsh 2y ago .join(Inbound.hosts)
149 01cdf2e Dawsh 2y ago .filter(User.id == user_id)
150 01cdf2e Dawsh 2y ago .all()
151 01cdf2e Dawsh 2y ago )
152 a47eb4c Dawsh 2y ago
153 12b255b Dawsh 2y ago
154 a47eb4c Dawsh 2y ago def get_inbound_hosts(db: Session, inbound_id: int) -> List[InboundHost]:
155 f1ab16c Dawsh 2y ago return (
156 f1ab16c Dawsh 2y ago db.query(InboundHost)
157 f1ab16c Dawsh 2y ago .filter(InboundHost.inbound_id == inbound_id)
158 f1ab16c Dawsh 2y ago .all()
159 f1ab16c Dawsh 2y ago )
160 a47eb4c Dawsh 2y ago
161 12b255b Dawsh 2y ago
162 a47eb4c Dawsh 2y ago def get_all_inbounds(db: Session):
163 a47eb4c Dawsh 2y ago return db.query(Inbound).all()
164 a47eb4c Dawsh 2y ago
165 a47eb4c Dawsh 2y ago
166 2de9d72 Dawsh 2y ago def get_inbound(db: Session, inbound_id: int) -> Inbound | None:
167 2de9d72 Dawsh 2y ago return db.query(Inbound).filter(Inbound.id == inbound_id).first()
168 a47eb4c Dawsh 2y ago
169 a47eb4c Dawsh 2y ago
170 2de9d72 Dawsh 2y ago def get_host(db: Session, host_id) -> InboundHost:
171 2de9d72 Dawsh 2y ago return db.query(InboundHost).filter(InboundHost.id == host_id).first()
172 a47eb4c Dawsh 2y ago
173 a47eb4c Dawsh 2y ago
174 a47eb4c Dawsh 2y ago def add_host(db: Session, inbound: Inbound, host: InboundHostModify):
175 2de9d72 Dawsh 2y ago host = InboundHost(
176 2de9d72 Dawsh 2y ago remark=host.remark,
177 2de9d72 Dawsh 2y ago address=host.address,
178 2de9d72 Dawsh 2y ago port=host.port,
179 2de9d72 Dawsh 2y ago path=host.path,
180 2de9d72 Dawsh 2y ago sni=host.sni,
181 2de9d72 Dawsh 2y ago host=host.host,
182 2de9d72 Dawsh 2y ago inbound=inbound,
183 2de9d72 Dawsh 2y ago security=host.security,
184 244c9d8 Dawsh 2y ago alpn=host.alpn.value,
185 01cdf2e Dawsh 2y ago fingerprint=host.fingerprint,
186 0b152b5 Mrdn 2y ago fragment=host.fragment.model_dump() if host.fragment else None,
187 0b152b5 Mrdn 2y ago mux=host.mux,
188 dd32f70 Dawsh 2y ago allowinsecure=host.allowinsecure,
189 e422d72 Dawsh 2y ago weight=host.weight,
190 a47eb4c Dawsh 2y ago )
191 2de9d72 Dawsh 2y ago inbound.hosts.append(host)
192 a47eb4c Dawsh 2y ago db.commit()
193 2de9d72 Dawsh 2y ago db.refresh(host)
194 2de9d72 Dawsh 2y ago return host
195 2de9d72 Dawsh 2y ago
196 2de9d72 Dawsh 2y ago
197 2de9d72 Dawsh 2y ago def update_host(db: Session, db_host: InboundHost, host: InboundHostModify):
198 2de9d72 Dawsh 2y ago db_host.remark = host.remark
199 2de9d72 Dawsh 2y ago db_host.address = host.address
200 2de9d72 Dawsh 2y ago db_host.port = host.port
201 2de9d72 Dawsh 2y ago db_host.path = host.path
202 2de9d72 Dawsh 2y ago db_host.sni = host.sni
203 2de9d72 Dawsh 2y ago db_host.host = host.host
204 2de9d72 Dawsh 2y ago db_host.security = host.security
205 244c9d8 Dawsh 2y ago db_host.alpn = host.alpn.value
206 2de9d72 Dawsh 2y ago db_host.fingerprint = host.fingerprint
207 0b152b5 Mrdn 2y ago db_host.fragment = host.fragment.model_dump() if host.fragment else None
208 0b152b5 Mrdn 2y ago db_host.mux = host.mux
209 a88ed47 Mardin 2y ago db_host.is_disabled = host.is_disabled
210 dd32f70 Dawsh 2y ago db_host.allowinsecure = host.allowinsecure
211 e422d72 Dawsh 2y ago db_host.weight = host.weight
212 2de9d72 Dawsh 2y ago db.commit()
213 2de9d72 Dawsh 2y ago db.refresh(db_host)
214 2de9d72 Dawsh 2y ago return db_host
215 a47eb4c Dawsh 2y ago
216 a47eb4c Dawsh 2y ago
217 a47eb4c Dawsh 2y ago def get_user(db: Session, username: str):
218 a47eb4c Dawsh 2y ago return db.query(User).filter(User.username == username).first()
219 a47eb4c Dawsh 2y ago
220 a47eb4c Dawsh 2y ago
221 a47eb4c Dawsh 2y ago def get_user_by_id(db: Session, user_id: int):
222 a47eb4c Dawsh 2y ago return db.query(User).filter(User.id == user_id).first()
223 a47eb4c Dawsh 2y ago
224 a47eb4c Dawsh 2y ago
225 01cdf2e Dawsh 2y ago UsersSortingOptions = Enum(
226 01cdf2e Dawsh 2y ago "UsersSortingOptions",
227 01cdf2e Dawsh 2y ago {
228 01cdf2e Dawsh 2y ago "username": User.username.asc(),
229 01cdf2e Dawsh 2y ago "used_traffic": User.used_traffic.asc(),
230 01cdf2e Dawsh 2y ago "data_limit": User.data_limit.asc(),
231 d377c4c Dawsh 2y ago "expire": User.expire_date.asc(),
232 01cdf2e Dawsh 2y ago "created_at": User.created_at.asc(),
233 01cdf2e Dawsh 2y ago "-username": User.username.desc(),
234 01cdf2e Dawsh 2y ago "-used_traffic": User.used_traffic.desc(),
235 01cdf2e Dawsh 2y ago "-data_limit": User.data_limit.desc(),
236 d377c4c Dawsh 2y ago "-expire": User.expire_date.desc(),
237 01cdf2e Dawsh 2y ago "-created_at": User.created_at.desc(),
238 01cdf2e Dawsh 2y ago },
239 01cdf2e Dawsh 2y ago )
240 01cdf2e Dawsh 2y ago
241 01cdf2e Dawsh 2y ago
242 01cdf2e Dawsh 2y ago def get_users(
243 01cdf2e Dawsh 2y ago db: Session,
244 01cdf2e Dawsh 2y ago offset: Optional[int] = None,
245 01cdf2e Dawsh 2y ago limit: Optional[int] = None,
246 01cdf2e Dawsh 2y ago usernames: Optional[List[str]] = None,
247 01cdf2e Dawsh 2y ago sort: Optional[List[UsersSortingOptions]] = None,
248 01cdf2e Dawsh 2y ago admin: Optional[Admin] = None,
249 d377c4c Dawsh 2y ago reset_strategy: Optional[Union[UserDataUsageResetStrategy, list]] = None,
250 d377c4c Dawsh 2y ago expire_strategy: (
251 d377c4c Dawsh 2y ago UserExpireStrategy | list[UserExpireStrategy] | None
252 d377c4c Dawsh 2y ago ) = None,
253 d377c4c Dawsh 2y ago is_active: bool | None = None,
254 d377c4c Dawsh 2y ago activated: bool | None = None,
255 d377c4c Dawsh 2y ago expired: bool | None = None,
256 d377c4c Dawsh 2y ago data_limit_reached: bool | None = None,
257 4708fcb Dawsh 2y ago enabled: bool | None = None,
258 01cdf2e Dawsh 2y ago ) -> Union[List[User], Tuple[List[User], int]]:
259 24826a2 Dawsh 2y ago query = db.query(User).filter(User.removed == False)
260 a47eb4c Dawsh 2y ago
261 a47eb4c Dawsh 2y ago if usernames:
262 a47eb4c Dawsh 2y ago if len(usernames) == 1:
263 a47eb4c Dawsh 2y ago query = query.filter(User.username.ilike(f"%{usernames[0]}%"))
264 a47eb4c Dawsh 2y ago else:
265 a47eb4c Dawsh 2y ago query = query.filter(User.username.in_(usernames))
266 a47eb4c Dawsh 2y ago
267 a47eb4c Dawsh 2y ago if reset_strategy:
268 a47eb4c Dawsh 2y ago if isinstance(reset_strategy, list):
269 f1ab16c Dawsh 2y ago query = query.filter(
270 f1ab16c Dawsh 2y ago User.data_limit_reset_strategy.in_(reset_strategy)
271 f1ab16c Dawsh 2y ago )
272 a47eb4c Dawsh 2y ago else:
273 f1ab16c Dawsh 2y ago query = query.filter(
274 f1ab16c Dawsh 2y ago User.data_limit_reset_strategy == reset_strategy
275 f1ab16c Dawsh 2y ago )
276 a47eb4c Dawsh 2y ago
277 d377c4c Dawsh 2y ago if expire_strategy:
278 d377c4c Dawsh 2y ago if isinstance(expire_strategy, list):
279 d377c4c Dawsh 2y ago query = query.filter(User.expire_strategy.in_(expire_strategy))
280 d377c4c Dawsh 2y ago else:
281 d377c4c Dawsh 2y ago query = query.filter(User.expire_strategy == expire_strategy)
282 d377c4c Dawsh 2y ago
283 d377c4c Dawsh 2y ago if isinstance(is_active, bool):
284 d377c4c Dawsh 2y ago query = query.filter(User.is_active == is_active)
285 d377c4c Dawsh 2y ago
286 d377c4c Dawsh 2y ago if isinstance(activated, bool):
287 d377c4c Dawsh 2y ago query = query.filter(User.activated == activated)
288 d377c4c Dawsh 2y ago
289 d377c4c Dawsh 2y ago if isinstance(expired, bool):
290 d377c4c Dawsh 2y ago query = query.filter(User.expired == expired)
291 d377c4c Dawsh 2y ago
292 d377c4c Dawsh 2y ago if isinstance(data_limit_reached, bool):
293 d377c4c Dawsh 2y ago query = query.filter(User.data_limit_reached == data_limit_reached)
294 d377c4c Dawsh 2y ago
295 4708fcb Dawsh 2y ago if isinstance(enabled, bool):
296 4708fcb Dawsh 2y ago query = query.filter(User.enabled == enabled)
297 4708fcb Dawsh 2y ago
298 a47eb4c Dawsh 2y ago if admin:
299 a47eb4c Dawsh 2y ago query = query.filter(User.admin == admin)
300 a47eb4c Dawsh 2y ago
301 a47eb4c Dawsh 2y ago if sort:
302 a47eb4c Dawsh 2y ago query = query.order_by(*(opt.value for opt in sort))
303 a47eb4c Dawsh 2y ago
304 a47eb4c Dawsh 2y ago if offset:
305 a47eb4c Dawsh 2y ago query = query.offset(offset)
306 d377c4c Dawsh 2y ago
307 a47eb4c Dawsh 2y ago if limit:
308 a47eb4c Dawsh 2y ago query = query.limit(limit)
309 a47eb4c Dawsh 2y ago
310 a47eb4c Dawsh 2y ago return query.all()
311 a47eb4c Dawsh 2y ago
312 a47eb4c Dawsh 2y ago
313 9ca312d Dawsh 2y ago def get_user_total_usage(
314 9ca312d Dawsh 2y ago db: Session, user: User, start: datetime, end: datetime, per_day=False
315 9ca312d Dawsh 2y ago ):
316 9ca312d Dawsh 2y ago usages = defaultdict(int)
317 9ca312d Dawsh 2y ago
318 9ca312d Dawsh 2y ago query = db.query(
319 9ca312d Dawsh 2y ago (
320 9ca312d Dawsh 2y ago cast(NodeUserUsage.created_at, Date).label("day")
321 9ca312d Dawsh 2y ago if per_day
322 9ca312d Dawsh 2y ago else NodeUserUsage.created_at
323 9ca312d Dawsh 2y ago ),
324 9ca312d Dawsh 2y ago func.sum(NodeUserUsage.used_traffic),
325 9ca312d Dawsh 2y ago ).filter(
326 9ca312d Dawsh 2y ago and_(
327 9ca312d Dawsh 2y ago NodeUserUsage.user_id == user.id,
328 9ca312d Dawsh 2y ago NodeUserUsage.created_at >= start,
329 9ca312d Dawsh 2y ago NodeUserUsage.created_at <= end,
330 9ca312d Dawsh 2y ago )
331 9ca312d Dawsh 2y ago )
332 9ca312d Dawsh 2y ago if per_day:
333 9ca312d Dawsh 2y ago query = query.group_by(cast(NodeUserUsage.created_at, Date))
334 9ca312d Dawsh 2y ago else:
335 9ca312d Dawsh 2y ago query = query.group_by(NodeUserUsage.created_at)
336 9ca312d Dawsh 2y ago
337 9ca312d Dawsh 2y ago for date, used_traffic in query:
338 9ca312d Dawsh 2y ago if per_day:
339 9ca312d Dawsh 2y ago timestamp = datetime(
340 9ca312d Dawsh 2y ago date.year, date.month, date.day, tzinfo=timezone.utc
341 9ca312d Dawsh 2y ago ).timestamp()
342 9ca312d Dawsh 2y ago usages[timestamp] += int(used_traffic)
343 9ca312d Dawsh 2y ago else:
344 9ca312d Dawsh 2y ago usages[date.replace(tzinfo=timezone.utc).timestamp()] += int(
345 9ca312d Dawsh 2y ago used_traffic
346 9ca312d Dawsh 2y ago )
347 9ca312d Dawsh 2y ago
348 9ca312d Dawsh 2y ago result = TrafficUsageSeries(usages=[])
349 9ca312d Dawsh 2y ago current = start.astimezone(timezone.utc).replace(
350 9ca312d Dawsh 2y ago minute=0, second=0, microsecond=0
351 9ca312d Dawsh 2y ago )
352 9ca312d Dawsh 2y ago if per_day:
353 9ca312d Dawsh 2y ago current = current.replace(hour=0)
354 9ca312d Dawsh 2y ago
355 9ca312d Dawsh 2y ago step = timedelta(days=1) if per_day else timedelta(hours=1)
356 9ca312d Dawsh 2y ago while current <= end.replace(tzinfo=timezone.utc):
357 9ca312d Dawsh 2y ago current_usage = usages.get(current.timestamp()) or 0
358 9ca312d Dawsh 2y ago result.usages.append((int(current.timestamp()), current_usage))
359 9ca312d Dawsh 2y ago result.total += current_usage
360 9ca312d Dawsh 2y ago current += step
361 9ca312d Dawsh 2y ago
362 9ca312d Dawsh 2y ago result.step = int(step.total_seconds())
363 9ca312d Dawsh 2y ago return result
364 9ca312d Dawsh 2y ago
365 9ca312d Dawsh 2y ago
366 6a4fee1 Dawsh 2y ago def get_total_usages(
367 6a4fee1 Dawsh 2y ago db: Session, admin: Admin, start: datetime, end: datetime
368 b15de9e Erfan 2y ago ) -> TrafficUsageSeries:
369 6a4fee1 Dawsh 2y ago usages = defaultdict(int)
370 6a4fee1 Dawsh 2y ago
371 6a4fee1 Dawsh 2y ago query = (
372 6a4fee1 Dawsh 2y ago db.query(
373 6a4fee1 Dawsh 2y ago NodeUserUsage.created_at, func.sum(NodeUserUsage.used_traffic)
374 6a4fee1 Dawsh 2y ago )
375 6a4fee1 Dawsh 2y ago .group_by(NodeUserUsage.created_at)
376 6a4fee1 Dawsh 2y ago .filter(
377 6a4fee1 Dawsh 2y ago and_(
378 6a4fee1 Dawsh 2y ago NodeUserUsage.created_at >= start,
379 6a4fee1 Dawsh 2y ago NodeUserUsage.created_at <= end,
380 6a4fee1 Dawsh 2y ago )
381 6a4fee1 Dawsh 2y ago )
382 6a4fee1 Dawsh 2y ago )
383 6a4fee1 Dawsh 2y ago
384 6a4fee1 Dawsh 2y ago if not admin.is_sudo:
385 6a4fee1 Dawsh 2y ago query = (
386 6a4fee1 Dawsh 2y ago query.filter(
387 6a4fee1 Dawsh 2y ago Admin.id == admin.id,
388 6a4fee1 Dawsh 2y ago )
389 6a4fee1 Dawsh 2y ago .join(User, NodeUserUsage.user_id == User.id)
390 6a4fee1 Dawsh 2y ago .join(Admin, User.admin_id == Admin.id)
391 6a4fee1 Dawsh 2y ago )
392 b15de9e Erfan 2y ago
393 6a4fee1 Dawsh 2y ago for created_at, used_traffic in query.all():
394 b15de9e Erfan 2y ago timestamp = created_at.replace(tzinfo=timezone.utc).timestamp()
395 b15de9e Erfan 2y ago usages[timestamp] += int(used_traffic)
396 6a4fee1 Dawsh 2y ago
397 b15de9e Erfan 2y ago result = TrafficUsageSeries(usages=[], total=0)
398 6a4fee1 Dawsh 2y ago current = start.astimezone(timezone.utc).replace(
399 6a4fee1 Dawsh 2y ago minute=0, second=0, microsecond=0
400 6a4fee1 Dawsh 2y ago )
401 6a4fee1 Dawsh 2y ago
402 6a4fee1 Dawsh 2y ago while current <= end.replace(tzinfo=timezone.utc):
403 b15de9e Erfan 2y ago usage = usages.get(current.timestamp()) or 0
404 b15de9e Erfan 2y ago result.usages.append((int(current.timestamp()), usage))
405 b15de9e Erfan 2y ago result.total += usage
406 6a4fee1 Dawsh 2y ago current += timedelta(hours=1)
407 6a4fee1 Dawsh 2y ago
408 6a4fee1 Dawsh 2y ago return result
409 6a4fee1 Dawsh 2y ago
410 6a4fee1 Dawsh 2y ago
411 01cdf2e Dawsh 2y ago def get_user_usages(
412 01cdf2e Dawsh 2y ago db: Session,
413 e6e6467 Dawsh 2y ago db_user: User,
414 01cdf2e Dawsh 2y ago start: datetime,
415 01cdf2e Dawsh 2y ago end: datetime,
416 e6e6467 Dawsh 2y ago ) -> UserUsageSeriesResponse:
417 b15de9e Erfan 2y ago
418 b15de9e Erfan 2y ago usages = defaultdict(dict)
419 b15de9e Erfan 2y ago
420 01cdf2e Dawsh 2y ago cond = and_(
421 e6e6467 Dawsh 2y ago NodeUserUsage.user_id == db_user.id,
422 01cdf2e Dawsh 2y ago NodeUserUsage.created_at >= start,
423 01cdf2e Dawsh 2y ago NodeUserUsage.created_at <= end,
424 01cdf2e Dawsh 2y ago )
425 a47eb4c Dawsh 2y ago
426 a47eb4c Dawsh 2y ago for v in db.query(NodeUserUsage).filter(cond):
427 b15de9e Erfan 2y ago timestamp = v.created_at.replace(tzinfo=timezone.utc).timestamp()
428 b15de9e Erfan 2y ago usages[v.node_id][timestamp] = v.used_traffic
429 e6e6467 Dawsh 2y ago
430 e6e6467 Dawsh 2y ago node_ids = list(usages.keys())
431 e6e6467 Dawsh 2y ago nodes = db.query(Node).where(Node.id.in_(node_ids))
432 e6e6467 Dawsh 2y ago node_id_names = {node.id: node.name for node in nodes}
433 e6e6467 Dawsh 2y ago
434 b15de9e Erfan 2y ago result = UserUsageSeriesResponse(
435 b15de9e Erfan 2y ago username=db_user.username, node_usages=[], total=0
436 b15de9e Erfan 2y ago )
437 b15de9e Erfan 2y ago
438 e6e6467 Dawsh 2y ago for node_id, rows in usages.items():
439 e6e6467 Dawsh 2y ago node_usages = UserNodeUsageSeries(
440 e6e6467 Dawsh 2y ago node_id=node_id, node_name=node_id_names[node_id], usages=[]
441 e6e6467 Dawsh 2y ago )
442 e6e6467 Dawsh 2y ago current = start.astimezone(timezone.utc).replace(
443 e6e6467 Dawsh 2y ago minute=0, second=0, microsecond=0
444 e6e6467 Dawsh 2y ago )
445 a47eb4c Dawsh 2y ago
446 e6e6467 Dawsh 2y ago while current <= end:
447 b15de9e Erfan 2y ago usage = rows.get(current.timestamp()) or 0
448 b15de9e Erfan 2y ago node_usages.usages.append((int(current.timestamp()), usage))
449 e6e6467 Dawsh 2y ago current += timedelta(hours=1)
450 b15de9e Erfan 2y ago result.total += usage
451 e6e6467 Dawsh 2y ago result.node_usages.append(node_usages)
452 b15de9e Erfan 2y ago
453 e6e6467 Dawsh 2y ago return result
454 a47eb4c Dawsh 2y ago
455 a47eb4c Dawsh 2y ago
456 e5dcd82 Dawsh 2y ago def get_users_count(
457 e5dcd82 Dawsh 2y ago db: Session,
458 e5dcd82 Dawsh 2y ago admin: Admin | None = None,
459 e5dcd82 Dawsh 2y ago enabled: bool | None = None,
460 e5dcd82 Dawsh 2y ago online: bool | None = None,
461 d377c4c Dawsh 2y ago expire_strategy: UserExpireStrategy | None = None,
462 d377c4c Dawsh 2y ago is_active: bool | None = None,
463 d377c4c Dawsh 2y ago expired: bool | None = None,
464 d377c4c Dawsh 2y ago data_limit_reached: bool | None = None,
465 e5dcd82 Dawsh 2y ago ):
466 45803f3 Dawsh 2y ago query = db.query(User.id).filter(User.removed == False)
467 a47eb4c Dawsh 2y ago if admin:
468 9ddfbc8 Mardin 2y ago query = query.filter(User.admin_id == admin.id)
469 d377c4c Dawsh 2y ago if is_active:
470 d377c4c Dawsh 2y ago query = query.filter(User.is_active == is_active)
471 d377c4c Dawsh 2y ago if expired:
472 d377c4c Dawsh 2y ago query = query.filter(User.expired == expired)
473 d377c4c Dawsh 2y ago if data_limit_reached:
474 d377c4c Dawsh 2y ago query = query.filter(User.data_limit_reached == data_limit_reached)
475 e5dcd82 Dawsh 2y ago if enabled:
476 e5dcd82 Dawsh 2y ago query = query.filter(User.enabled == enabled)
477 d377c4c Dawsh 2y ago if online is True:
478 e5dcd82 Dawsh 2y ago query = query.filter(
479 e5dcd82 Dawsh 2y ago User.online_at > (datetime.utcnow() - timedelta(seconds=30))
480 e5dcd82 Dawsh 2y ago )
481 d377c4c Dawsh 2y ago elif online is False:
482 d377c4c Dawsh 2y ago query = query.filter(
483 d377c4c Dawsh 2y ago User.online_at < (datetime.utcnow() - timedelta(seconds=30))
484 d377c4c Dawsh 2y ago )
485 d377c4c Dawsh 2y ago if expire_strategy:
486 d377c4c Dawsh 2y ago query = query.filter(User.expire_strategy == expire_strategy)
487 d377c4c Dawsh 2y ago
488 a47eb4c Dawsh 2y ago return query.count()
489 a47eb4c Dawsh 2y ago
490 a47eb4c Dawsh 2y ago
491 4708fcb Dawsh 2y ago def create_user(
492 4708fcb Dawsh 2y ago db: Session,
493 4708fcb Dawsh 2y ago user: UserCreate,
494 4708fcb Dawsh 2y ago admin: Admin = None,
495 4708fcb Dawsh 2y ago allowed_services: list | None = None,
496 4708fcb Dawsh 2y ago ):
497 4708fcb Dawsh 2y ago service_ids = (
498 4708fcb Dawsh 2y ago [sid for sid in user.service_ids if sid in allowed_services]
499 4708fcb Dawsh 2y ago if allowed_services is not None
500 4708fcb Dawsh 2y ago else user.service_ids
501 4708fcb Dawsh 2y ago )
502 a47eb4c Dawsh 2y ago dbuser = User(
503 a47eb4c Dawsh 2y ago username=user.username,
504 a47eb4c Dawsh 2y ago key=user.key,
505 d377c4c Dawsh 2y ago expire_strategy=user.expire_strategy,
506 d377c4c Dawsh 2y ago expire_date=user.expire_date,
507 d377c4c Dawsh 2y ago usage_duration=user.usage_duration,
508 d377c4c Dawsh 2y ago activation_deadline=user.activation_deadline,
509 01cdf2e Dawsh 2y ago services=db.query(Service)
510 4708fcb Dawsh 2y ago .filter(Service.id.in_(service_ids))
511 01cdf2e Dawsh 2y ago .all(), # user.services,
512 a47eb4c Dawsh 2y ago data_limit=(user.data_limit or None),
513 a47eb4c Dawsh 2y ago admin=admin,
514 a47eb4c Dawsh 2y ago data_limit_reset_strategy=user.data_limit_reset_strategy,
515 a47eb4c Dawsh 2y ago note=user.note,
516 a47eb4c Dawsh 2y ago )
517 a47eb4c Dawsh 2y ago db.add(dbuser)
518 a47eb4c Dawsh 2y ago db.commit()
519 a47eb4c Dawsh 2y ago db.refresh(dbuser)
520 a47eb4c Dawsh 2y ago return dbuser
521 a47eb4c Dawsh 2y ago
522 a47eb4c Dawsh 2y ago
523 a47eb4c Dawsh 2y ago def remove_user(db: Session, dbuser: User):
524 fdd3f61 Dawsh 2y ago dbuser.username = None
525 24826a2 Dawsh 2y ago dbuser.removed = True
526 24826a2 Dawsh 2y ago dbuser.activated = False
527 a47eb4c Dawsh 2y ago # db.query(User).filter_by(id=user_id).delete()
528 a47eb4c Dawsh 2y ago db.commit()
529 a47eb4c Dawsh 2y ago
530 a47eb4c Dawsh 2y ago
531 4708fcb Dawsh 2y ago def update_user(
532 4708fcb Dawsh 2y ago db: Session,
533 4708fcb Dawsh 2y ago dbuser: User,
534 4708fcb Dawsh 2y ago modify: UserModify,
535 4708fcb Dawsh 2y ago allowed_services: list | None = None,
536 4708fcb Dawsh 2y ago ):
537 a47eb4c Dawsh 2y ago if modify.data_limit is not None:
538 d377c4c Dawsh 2y ago dbuser.data_limit = modify.data_limit or None
539 d377c4c Dawsh 2y ago
540 d377c4c Dawsh 2y ago if modify.expire_strategy is not None:
541 d377c4c Dawsh 2y ago dbuser.expire_strategy = modify.expire_strategy or None
542 d377c4c Dawsh 2y ago
543 4442e87 mahdim10 2y ago if modify.expire_strategy == UserExpireStrategy.FIXED_DATE:
544 4442e87 mahdim10 2y ago dbuser.usage_duration = None
545 4442e87 mahdim10 2y ago dbuser.activation_deadline = None
546 4442e87 mahdim10 2y ago elif modify.expire_strategy == UserExpireStrategy.START_ON_FIRST_USE:
547 4442e87 mahdim10 2y ago dbuser.expire_date = None
548 4442e87 mahdim10 2y ago elif modify.expire_strategy == UserExpireStrategy.NEVER:
549 4442e87 mahdim10 2y ago dbuser.expire_date = None
550 4442e87 mahdim10 2y ago dbuser.usage_duration = None
551 4442e87 mahdim10 2y ago dbuser.activation_deadline = None
552 4442e87 mahdim10 2y ago
553 d377c4c Dawsh 2y ago if modify.expire_date is not None:
554 d377c4c Dawsh 2y ago dbuser.expire_date = modify.expire_date or None
555 a47eb4c Dawsh 2y ago
556 a47eb4c Dawsh 2y ago if modify.note is not None:
557 a47eb4c Dawsh 2y ago dbuser.note = modify.note or None
558 a47eb4c Dawsh 2y ago
559 a47eb4c Dawsh 2y ago if modify.data_limit_reset_strategy is not None:
560 d377c4c Dawsh 2y ago dbuser.data_limit_reset_strategy = modify.data_limit_reset_strategy
561 a47eb4c Dawsh 2y ago
562 d377c4c Dawsh 2y ago if modify.activation_deadline is not None:
563 d377c4c Dawsh 2y ago dbuser.activation_deadline = modify.activation_deadline
564 a47eb4c Dawsh 2y ago
565 d377c4c Dawsh 2y ago if modify.usage_duration is not None:
566 d377c4c Dawsh 2y ago dbuser.usage_duration = modify.usage_duration
567 2de9d72 Dawsh 2y ago
568 db68a58 Dawsh 2y ago if modify.service_ids is not None:
569 4708fcb Dawsh 2y ago if allowed_services is not None:
570 4708fcb Dawsh 2y ago service_ids = [
571 4708fcb Dawsh 2y ago sid for sid in modify.service_ids if sid in allowed_services
572 4708fcb Dawsh 2y ago ]
573 4708fcb Dawsh 2y ago else:
574 4708fcb Dawsh 2y ago service_ids = modify.service_ids
575 4708fcb Dawsh 2y ago
576 01cdf2e Dawsh 2y ago dbuser.services = (
577 4708fcb Dawsh 2y ago db.query(Service).filter(Service.id.in_(service_ids)).all()
578 01cdf2e Dawsh 2y ago )
579 a47eb4c Dawsh 2y ago dbuser.edit_at = datetime.utcnow()
580 a47eb4c Dawsh 2y ago
581 a47eb4c Dawsh 2y ago db.commit()
582 a47eb4c Dawsh 2y ago db.refresh(dbuser)
583 a47eb4c Dawsh 2y ago return dbuser
584 a47eb4c Dawsh 2y ago
585 a47eb4c Dawsh 2y ago
586 a47eb4c Dawsh 2y ago def reset_user_data_usage(db: Session, dbuser: User):
587 42a1073 Dawsh 2y ago dbuser.traffic_reset_at = datetime.utcnow()
588 a47eb4c Dawsh 2y ago
589 a47eb4c Dawsh 2y ago dbuser.used_traffic = 0
590 42a1073 Dawsh 2y ago
591 a47eb4c Dawsh 2y ago db.add(dbuser)
592 a47eb4c Dawsh 2y ago
593 a47eb4c Dawsh 2y ago db.commit()
594 a47eb4c Dawsh 2y ago db.refresh(dbuser)
595 a47eb4c Dawsh 2y ago return dbuser
596 a47eb4c Dawsh 2y ago
597 a47eb4c Dawsh 2y ago
598 a47eb4c Dawsh 2y ago def revoke_user_sub(db: Session, dbuser: User):
599 34a7612 Dawsh 2y ago dbuser.key = secrets.token_hex(16)
600 00d6be5 Erfan 2y ago dbuser.sub_revoked_at = datetime.utcnow()
601 a47eb4c Dawsh 2y ago db.commit()
602 a47eb4c Dawsh 2y ago db.refresh(dbuser)
603 a47eb4c Dawsh 2y ago return dbuser
604 a47eb4c Dawsh 2y ago
605 a47eb4c Dawsh 2y ago
606 a47eb4c Dawsh 2y ago def update_user_sub(db: Session, dbuser: User, user_agent: str):
607 a47eb4c Dawsh 2y ago dbuser.sub_updated_at = datetime.utcnow()
608 a47eb4c Dawsh 2y ago dbuser.sub_last_user_agent = user_agent
609 a47eb4c Dawsh 2y ago
610 a47eb4c Dawsh 2y ago db.commit()
611 a47eb4c Dawsh 2y ago db.refresh(dbuser)
612 a47eb4c Dawsh 2y ago return dbuser
613 a47eb4c Dawsh 2y ago
614 a47eb4c Dawsh 2y ago
615 a47eb4c Dawsh 2y ago def reset_all_users_data_usage(db: Session, admin: Optional[Admin] = None):
616 a47eb4c Dawsh 2y ago query = db.query(User)
617 a47eb4c Dawsh 2y ago
618 a47eb4c Dawsh 2y ago if admin:
619 a47eb4c Dawsh 2y ago query = query.filter(User.admin == admin)
620 a47eb4c Dawsh 2y ago
621 d377c4c Dawsh 2y ago for db_user in query.all():
622 d377c4c Dawsh 2y ago db_user.used_traffic = 0
623 a47eb4c Dawsh 2y ago
624 a47eb4c Dawsh 2y ago db.commit()
625 a47eb4c Dawsh 2y ago
626 a47eb4c Dawsh 2y ago
627 a47eb4c Dawsh 2y ago def update_user_status(db: Session, dbuser: User, status: UserStatus):
628 a47eb4c Dawsh 2y ago dbuser.status = status
629 a47eb4c Dawsh 2y ago db.commit()
630 a47eb4c Dawsh 2y ago db.refresh(dbuser)
631 a47eb4c Dawsh 2y ago return dbuser
632 a47eb4c Dawsh 2y ago
633 a47eb4c Dawsh 2y ago
634 a47eb4c Dawsh 2y ago def set_owner(db: Session, dbuser: User, admin: Admin):
635 a47eb4c Dawsh 2y ago dbuser.admin = admin
636 a47eb4c Dawsh 2y ago db.commit()
637 a47eb4c Dawsh 2y ago db.refresh(dbuser)
638 a47eb4c Dawsh 2y ago return dbuser
639 a47eb4c Dawsh 2y ago
640 a47eb4c Dawsh 2y ago
641 a47eb4c Dawsh 2y ago def get_system_usage(db: Session):
642 a47eb4c Dawsh 2y ago return db.query(System).first()
643 a47eb4c Dawsh 2y ago
644 a47eb4c Dawsh 2y ago
645 a47eb4c Dawsh 2y ago def get_jwt_secret_key(db: Session):
646 a47eb4c Dawsh 2y ago return db.query(JWT).first().secret_key
647 a47eb4c Dawsh 2y ago
648 a47eb4c Dawsh 2y ago
649 a47eb4c Dawsh 2y ago def get_tls_certificate(db: Session):
650 a47eb4c Dawsh 2y ago return db.query(TLS).first()
651 a47eb4c Dawsh 2y ago
652 a47eb4c Dawsh 2y ago
653 4708fcb Dawsh 2y ago def get_admin(db: Session, username: str) -> Admin | None:
654 a47eb4c Dawsh 2y ago return db.query(Admin).filter(Admin.username == username).first()
655 a47eb4c Dawsh 2y ago
656 a47eb4c Dawsh 2y ago
657 a47eb4c Dawsh 2y ago def create_admin(db: Session, admin: AdminCreate):
658 a47eb4c Dawsh 2y ago dbadmin = Admin(
659 a47eb4c Dawsh 2y ago username=admin.username,
660 a47eb4c Dawsh 2y ago hashed_password=admin.hashed_password,
661 01cdf2e Dawsh 2y ago is_sudo=admin.is_sudo,
662 4708fcb Dawsh 2y ago enabled=admin.enabled,
663 4708fcb Dawsh 2y ago all_services_access=admin.all_services_access,
664 4708fcb Dawsh 2y ago modify_users_access=admin.modify_users_access,
665 4708fcb Dawsh 2y ago services=db.query(Service)
666 4708fcb Dawsh 2y ago .filter(Service.id.in_(admin.service_ids))
667 4708fcb Dawsh 2y ago .all(),
668 4708fcb Dawsh 2y ago subscription_url_prefix=admin.subscription_url_prefix,
669 a47eb4c Dawsh 2y ago )
670 a47eb4c Dawsh 2y ago db.add(dbadmin)
671 a47eb4c Dawsh 2y ago db.commit()
672 a47eb4c Dawsh 2y ago db.refresh(dbadmin)
673 a47eb4c Dawsh 2y ago return dbadmin
674 a47eb4c Dawsh 2y ago
675 a47eb4c Dawsh 2y ago
676 4708fcb Dawsh 2y ago def update_admin(
677 4708fcb Dawsh 2y ago db: Session, dbadmin: Admin, modifications: AdminPartialModify
678 4708fcb Dawsh 2y ago ):
679 4708fcb Dawsh 2y ago for attribute in [
680 4708fcb Dawsh 2y ago "is_sudo",
681 4708fcb Dawsh 2y ago "hashed_password",
682 4708fcb Dawsh 2y ago "enabled",
683 4708fcb Dawsh 2y ago "all_services_access",
684 4708fcb Dawsh 2y ago "modify_users_access",
685 4708fcb Dawsh 2y ago "subscription_url_prefix",
686 4708fcb Dawsh 2y ago ]:
687 4708fcb Dawsh 2y ago if not isinstance(getattr(modifications, attribute), NoneType):
688 4708fcb Dawsh 2y ago setattr(dbadmin, attribute, getattr(modifications, attribute))
689 4708fcb Dawsh 2y ago if attribute == "hashed_password":
690 4708fcb Dawsh 2y ago dbadmin.password_reset_at = datetime.utcnow()
691 4708fcb Dawsh 2y ago if isinstance(modifications.service_ids, list):
692 4708fcb Dawsh 2y ago dbadmin.services = (
693 4708fcb Dawsh 2y ago db.query(Service)
694 4708fcb Dawsh 2y ago .filter(Service.id.in_(modifications.service_ids))
695 4708fcb Dawsh 2y ago .all()
696 4708fcb Dawsh 2y ago )
697 a47eb4c Dawsh 2y ago db.commit()
698 a47eb4c Dawsh 2y ago db.refresh(dbadmin)
699 2de9d72 Dawsh 2y ago return dbadmin
700 a47eb4c Dawsh 2y ago
701 a47eb4c Dawsh 2y ago
702 01cdf2e Dawsh 2y ago def partial_update_admin(
703 01cdf2e Dawsh 2y ago db: Session, dbadmin: Admin, modified_admin: AdminPartialModify
704 01cdf2e Dawsh 2y ago ):
705 a47eb4c Dawsh 2y ago if modified_admin.is_sudo is not None:
706 a47eb4c Dawsh 2y ago dbadmin.is_sudo = modified_admin.is_sudo
707 01cdf2e Dawsh 2y ago if (
708 01cdf2e Dawsh 2y ago modified_admin.password is not None
709 01cdf2e Dawsh 2y ago and dbadmin.hashed_password != modified_admin.hashed_password
710 01cdf2e Dawsh 2y ago ):
711 a47eb4c Dawsh 2y ago dbadmin.hashed_password = modified_admin.hashed_password
712 a47eb4c Dawsh 2y ago dbadmin.password_reset_at = datetime.utcnow()
713 a47eb4c Dawsh 2y ago
714 a47eb4c Dawsh 2y ago db.commit()
715 a47eb4c Dawsh 2y ago db.refresh(dbadmin)
716 a47eb4c Dawsh 2y ago return dbadmin
717 a47eb4c Dawsh 2y ago
718 a47eb4c Dawsh 2y ago
719 a47eb4c Dawsh 2y ago def remove_admin(db: Session, dbadmin: Admin):
720 a47eb4c Dawsh 2y ago db.delete(dbadmin)
721 a47eb4c Dawsh 2y ago db.commit()
722 a47eb4c Dawsh 2y ago return dbadmin
723 a47eb4c Dawsh 2y ago
724 a47eb4c Dawsh 2y ago
725 01cdf2e Dawsh 2y ago def get_admins(
726 01cdf2e Dawsh 2y ago db: Session,
727 01cdf2e Dawsh 2y ago offset: Optional[int] = None,
728 01cdf2e Dawsh 2y ago limit: Optional[int] = None,
729 01cdf2e Dawsh 2y ago username: Optional[str] = None,
730 01cdf2e Dawsh 2y ago ):
731 a47eb4c Dawsh 2y ago query = db.query(Admin)
732 a47eb4c Dawsh 2y ago if username:
733 01cdf2e Dawsh 2y ago query = query.filter(Admin.username.ilike(f"%{username}%"))
734 a47eb4c Dawsh 2y ago if offset:
735 a47eb4c Dawsh 2y ago query = query.offset(offset)
736 a47eb4c Dawsh 2y ago if limit:
737 a47eb4c Dawsh 2y ago query = query.limit(limit)
738 a47eb4c Dawsh 2y ago return query.all()
739 a47eb4c Dawsh 2y ago
740 a47eb4c Dawsh 2y ago
741 ee1351a Dawsh 2y ago def create_service(db: Session, service: ServiceCreate) -> Service:
742 a47eb4c Dawsh 2y ago dbservice = Service(
743 a47eb4c Dawsh 2y ago name=service.name,
744 f1ab16c Dawsh 2y ago inbounds=db.query(Inbound)
745 f1ab16c Dawsh 2y ago .filter(Inbound.id.in_(service.inbound_ids))
746 f1ab16c Dawsh 2y ago .all(),
747 db68a58 Dawsh 2y ago users=[],
748 2de9d72 Dawsh 2y ago )
749 a47eb4c Dawsh 2y ago db.add(dbservice)
750 a47eb4c Dawsh 2y ago db.commit()
751 a47eb4c Dawsh 2y ago db.refresh(dbservice)
752 a47eb4c Dawsh 2y ago return dbservice
753 a47eb4c Dawsh 2y ago
754 a47eb4c Dawsh 2y ago
755 ee1351a Dawsh 2y ago def get_service(db: Session, service_id: id) -> Service:
756 ee1351a Dawsh 2y ago return db.query(Service).filter(Service.id == service_id).first()
757 a47eb4c Dawsh 2y ago
758 12b255b Dawsh 2y ago
759 a47eb4c Dawsh 2y ago def get_services(db: Session) -> List[Service]:
760 a47eb4c Dawsh 2y ago return db.query(Service).all()
761 a47eb4c Dawsh 2y ago
762 12b255b Dawsh 2y ago
763 f1ab16c Dawsh 2y ago def update_service(
764 f1ab16c Dawsh 2y ago db: Session, db_service: Service, modification: ServiceModify
765 f1ab16c Dawsh 2y ago ):
766 ee1351a Dawsh 2y ago if modification.name is not None:
767 ee1351a Dawsh 2y ago db_service.name = modification.name
768 ee1351a Dawsh 2y ago
769 db68a58 Dawsh 2y ago if modification.inbound_ids is not None:
770 01cdf2e Dawsh 2y ago db_service.inbounds = (
771 f1ab16c Dawsh 2y ago db.query(Inbound)
772 f1ab16c Dawsh 2y ago .filter(Inbound.id.in_(modification.inbound_ids))
773 f1ab16c Dawsh 2y ago .all()
774 01cdf2e Dawsh 2y ago )
775 ee1351a Dawsh 2y ago
776 ee1351a Dawsh 2y ago db.commit()
777 ee1351a Dawsh 2y ago db.refresh(db_service)
778 ee1351a Dawsh 2y ago return db_service
779 ee1351a Dawsh 2y ago
780 ee1351a Dawsh 2y ago
781 ee1351a Dawsh 2y ago def remove_service(db: Session, db_service: Service):
782 ee1351a Dawsh 2y ago db.delete(db_service)
783 ee1351a Dawsh 2y ago db.commit()
784 ee1351a Dawsh 2y ago return db_service
785 ee1351a Dawsh 2y ago
786 ee1351a Dawsh 2y ago
787 a47eb4c Dawsh 2y ago def get_node(db: Session, name: str):
788 a47eb4c Dawsh 2y ago return db.query(Node).filter(Node.name == name).first()
789 a47eb4c Dawsh 2y ago
790 a47eb4c Dawsh 2y ago
791 a47eb4c Dawsh 2y ago def get_node_by_id(db: Session, node_id: int):
792 a47eb4c Dawsh 2y ago return db.query(Node).filter(Node.id == node_id).first()
793 a47eb4c Dawsh 2y ago
794 a47eb4c Dawsh 2y ago
795 01cdf2e Dawsh 2y ago def get_nodes(
796 f1ab16c Dawsh 2y ago db: Session,
797 f1ab16c Dawsh 2y ago status: Optional[Union[NodeStatus, list]] = None,
798 f1ab16c Dawsh 2y ago enabled: bool = None,
799 01cdf2e Dawsh 2y ago ):
800 a47eb4c Dawsh 2y ago query = db.query(Node)
801 a47eb4c Dawsh 2y ago
802 a47eb4c Dawsh 2y ago if status:
803 a47eb4c Dawsh 2y ago if isinstance(status, list):
804 a47eb4c Dawsh 2y ago query = query.filter(Node.status.in_(status))
805 a47eb4c Dawsh 2y ago else:
806 a47eb4c Dawsh 2y ago query = query.filter(Node.status == status)
807 a47eb4c Dawsh 2y ago
808 a47eb4c Dawsh 2y ago if enabled:
809 a47eb4c Dawsh 2y ago query = query.filter(Node.status != NodeStatus.disabled)
810 a47eb4c Dawsh 2y ago
811 a47eb4c Dawsh 2y ago return query.all()
812 a47eb4c Dawsh 2y ago
813 a47eb4c Dawsh 2y ago
814 78a3e64 Dawsh 2y ago def get_node_usage(
815 78a3e64 Dawsh 2y ago db: Session, start: datetime, end: datetime, node: Node
816 78a3e64 Dawsh 2y ago ) -> TrafficUsageSeries:
817 78a3e64 Dawsh 2y ago usages = defaultdict(int)
818 a47eb4c Dawsh 2y ago
819 78a3e64 Dawsh 2y ago query = (
820 78a3e64 Dawsh 2y ago db.query(
821 78a3e64 Dawsh 2y ago NodeUserUsage.created_at, func.sum(NodeUserUsage.used_traffic)
822 78a3e64 Dawsh 2y ago )
823 78a3e64 Dawsh 2y ago .group_by(NodeUserUsage.created_at)
824 78a3e64 Dawsh 2y ago .filter(
825 78a3e64 Dawsh 2y ago and_(
826 78a3e64 Dawsh 2y ago NodeUserUsage.node_id == node.id,
827 78a3e64 Dawsh 2y ago NodeUserUsage.created_at >= start,
828 78a3e64 Dawsh 2y ago NodeUserUsage.created_at <= end,
829 78a3e64 Dawsh 2y ago )
830 78a3e64 Dawsh 2y ago )
831 a47eb4c Dawsh 2y ago )
832 78a3e64 Dawsh 2y ago
833 78a3e64 Dawsh 2y ago for created_at, used_traffic in query.all():
834 78a3e64 Dawsh 2y ago usages[created_at.replace(tzinfo=timezone.utc).timestamp()] += int(
835 78a3e64 Dawsh 2y ago used_traffic
836 a47eb4c Dawsh 2y ago )
837 a47eb4c Dawsh 2y ago
838 78a3e64 Dawsh 2y ago result = TrafficUsageSeries(usages=[], total=0)
839 78a3e64 Dawsh 2y ago current = start.astimezone(timezone.utc).replace(
840 78a3e64 Dawsh 2y ago minute=0, second=0, microsecond=0
841 78a3e64 Dawsh 2y ago )
842 a47eb4c Dawsh 2y ago
843 78a3e64 Dawsh 2y ago while current <= end.replace(tzinfo=timezone.utc):
844 78a3e64 Dawsh 2y ago usage = usages.get(current.timestamp()) or 0
845 b4ec790 Dawsh 2y ago result.usages.append((int(current.timestamp()), usage))
846 78a3e64 Dawsh 2y ago result.total += usage
847 78a3e64 Dawsh 2y ago current += timedelta(hours=1)
848 a47eb4c Dawsh 2y ago
849 78a3e64 Dawsh 2y ago return result
850 a47eb4c Dawsh 2y ago
851 a47eb4c Dawsh 2y ago
852 a47eb4c Dawsh 2y ago def create_node(db: Session, node: NodeCreate):
853 01cdf2e Dawsh 2y ago dbnode = Node(
854 01cdf2e Dawsh 2y ago name=node.name,
855 01cdf2e Dawsh 2y ago address=node.address,
856 01cdf2e Dawsh 2y ago port=node.port,
857 01cdf2e Dawsh 2y ago connection_backend=node.connection_backend,
858 01cdf2e Dawsh 2y ago )
859 a47eb4c Dawsh 2y ago
860 a47eb4c Dawsh 2y ago db.add(dbnode)
861 a47eb4c Dawsh 2y ago db.commit()
862 a47eb4c Dawsh 2y ago db.refresh(dbnode)
863 a47eb4c Dawsh 2y ago return dbnode
864 a47eb4c Dawsh 2y ago
865 a47eb4c Dawsh 2y ago
866 a47eb4c Dawsh 2y ago def remove_node(db: Session, dbnode: Node):
867 a47eb4c Dawsh 2y ago db.delete(dbnode)
868 a47eb4c Dawsh 2y ago db.commit()
869 a47eb4c Dawsh 2y ago return dbnode
870 a47eb4c Dawsh 2y ago
871 a47eb4c Dawsh 2y ago
872 a47eb4c Dawsh 2y ago def update_node(db: Session, dbnode: Node, modify: NodeModify):
873 a47eb4c Dawsh 2y ago if modify.name is not None:
874 a47eb4c Dawsh 2y ago dbnode.name = modify.name
875 a47eb4c Dawsh 2y ago
876 a47eb4c Dawsh 2y ago if modify.address is not None:
877 a47eb4c Dawsh 2y ago dbnode.address = modify.address
878 a47eb4c Dawsh 2y ago
879 a47eb4c Dawsh 2y ago if modify.port is not None:
880 a47eb4c Dawsh 2y ago dbnode.port = modify.port
881 a47eb4c Dawsh 2y ago
882 a47eb4c Dawsh 2y ago if modify.status is NodeStatus.disabled:
883 a47eb4c Dawsh 2y ago dbnode.status = modify.status
884 a47eb4c Dawsh 2y ago dbnode.xray_version = None
885 a47eb4c Dawsh 2y ago dbnode.message = None
886 a47eb4c Dawsh 2y ago else:
887 12b255b Dawsh 2y ago dbnode.status = NodeStatus.unhealthy
888 a47eb4c Dawsh 2y ago
889 a47eb4c Dawsh 2y ago if modify.usage_coefficient:
890 a47eb4c Dawsh 2y ago dbnode.usage_coefficient = modify.usage_coefficient
891 a47eb4c Dawsh 2y ago
892 5584d4a Mrdn 2y ago if modify.connection_backend:
893 5584d4a Mrdn 2y ago dbnode.connection_backend = modify.connection_backend
894 5584d4a Mrdn 2y ago
895 a47eb4c Dawsh 2y ago db.commit()
896 a47eb4c Dawsh 2y ago db.refresh(dbnode)
897 a47eb4c Dawsh 2y ago return dbnode
898 a47eb4c Dawsh 2y ago
899 a47eb4c Dawsh 2y ago
900 01cdf2e Dawsh 2y ago def update_node_status(
901 01cdf2e Dawsh 2y ago db: Session,
902 01cdf2e Dawsh 2y ago node_id: int,
903 01cdf2e Dawsh 2y ago status: NodeStatus,
904 01cdf2e Dawsh 2y ago message: str = None,
905 01cdf2e Dawsh 2y ago version: str = None,
906 01cdf2e Dawsh 2y ago ):
907 f6a32ea Dawsh 2y ago db_node = db.query(Node).where(Node.id == node_id).first()
908 f6a32ea Dawsh 2y ago db_node.status = status
909 f6a32ea Dawsh 2y ago if message:
910 f6a32ea Dawsh 2y ago db_node.message = message
911 f6a32ea Dawsh 2y ago db_node.last_status_change = datetime.utcnow()
912 a47eb4c Dawsh 2y ago db.commit()
913 a47eb4c Dawsh 2y ago
914 a47eb4c Dawsh 2y ago
915 a47eb4c Dawsh 2y ago def create_notification_reminder(
916 f1ab16c Dawsh 2y ago db: Session,
917 f1ab16c Dawsh 2y ago reminder_type: ReminderType,
918 f1ab16c Dawsh 2y ago expires_at: datetime,
919 f1ab16c Dawsh 2y ago user_id: int,
920 01cdf2e Dawsh 2y ago ) -> NotificationReminder:
921 01cdf2e Dawsh 2y ago reminder = NotificationReminder(
922 01cdf2e Dawsh 2y ago type=reminder_type, expires_at=expires_at, user_id=user_id
923 01cdf2e Dawsh 2y ago )
924 a47eb4c Dawsh 2y ago db.add(reminder)
925 a47eb4c Dawsh 2y ago db.commit()
926 a47eb4c Dawsh 2y ago db.refresh(reminder)
927 a47eb4c Dawsh 2y ago return reminder
928 a47eb4c Dawsh 2y ago
929 a47eb4c Dawsh 2y ago
930 a47eb4c Dawsh 2y ago def get_notification_reminder(
931 01cdf2e Dawsh 2y ago db: Session,
932 01cdf2e Dawsh 2y ago user_id: int,
933 01cdf2e Dawsh 2y ago reminder_type: ReminderType,
934 12b255b Dawsh 2y ago ) -> Optional[NotificationReminder]:
935 01cdf2e Dawsh 2y ago reminder = (
936 01cdf2e Dawsh 2y ago db.query(NotificationReminder)
937 01cdf2e Dawsh 2y ago .filter(NotificationReminder.user_id == user_id)
938 01cdf2e Dawsh 2y ago .filter(NotificationReminder.type == reminder_type)
939 01cdf2e Dawsh 2y ago .first()
940 01cdf2e Dawsh 2y ago )
941 a47eb4c Dawsh 2y ago if reminder is None:
942 a47eb4c Dawsh 2y ago return
943 a47eb4c Dawsh 2y ago if reminder.expires_at and reminder.expires_at < datetime.utcnow():
944 a47eb4c Dawsh 2y ago db.delete(reminder)
945 a47eb4c Dawsh 2y ago db.commit()
946 a47eb4c Dawsh 2y ago return
947 a47eb4c Dawsh 2y ago return reminder
948 a47eb4c Dawsh 2y ago
949 a47eb4c Dawsh 2y ago
950 01cdf2e Dawsh 2y ago def delete_notification_reminder_by_type(
951 01cdf2e Dawsh 2y ago db: Session, user_id: int, reminder_type: ReminderType
952 01cdf2e Dawsh 2y ago ) -> None:
953 a47eb4c Dawsh 2y ago """Deletes notification reminder filtered by user_id and type if exists"""
954 a47eb4c Dawsh 2y ago stmt = delete(NotificationReminder).where(
955 a47eb4c Dawsh 2y ago NotificationReminder.user_id == user_id,
956 a47eb4c Dawsh 2y ago NotificationReminder.type == reminder_type,
957 a47eb4c Dawsh 2y ago )
958 a47eb4c Dawsh 2y ago db.execute(stmt)
959 a47eb4c Dawsh 2y ago db.commit()
960 a47eb4c Dawsh 2y ago return
961 a47eb4c Dawsh 2y ago
962 a47eb4c Dawsh 2y ago
963 f1ab16c Dawsh 2y ago def delete_notification_reminder(
964 f1ab16c Dawsh 2y ago db: Session, dbreminder: NotificationReminder
965 f1ab16c Dawsh 2y ago ) -> None:
966 a47eb4c Dawsh 2y ago db.delete(dbreminder)
967 a47eb4c Dawsh 2y ago db.commit()
968 a47eb4c Dawsh 2y ago return