reyserver 1.1.49__py3-none-any.whl → 1.1.51__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
reyserver/rauth.py CHANGED
@@ -9,17 +9,23 @@
9
9
  """
10
10
 
11
11
 
12
+ from typing import Literal
12
13
  from fastapi import APIRouter
13
- from reydb import rorm
14
+ from reydb import rorm, DatabaseEngine, DatabaseEngineAsync
15
+ # from reykit.rdata import encode_jwt, is_hash_bcrypt
16
+ # from reykit.rtime import now
14
17
 
15
18
  from .rbase import ServerConfig, Bind, exit_api
16
19
 
17
20
 
18
21
  __all__ = (
19
- 'DatabaseORMTableInfo',
20
- 'DatabaseORMTableData',
21
- 'build_file_db',
22
- 'file_router'
22
+ 'DatabaseORMTableUser',
23
+ 'DatabaseORMTableRole',
24
+ 'DatabaseORMTablePerm',
25
+ 'DatabaseORMTableUserRole',
26
+ 'DatabaseORMTableRolePerm',
27
+ 'build_auth_db',
28
+ 'auth_router'
23
29
  )
24
30
 
25
31
 
@@ -34,10 +40,10 @@ class DatabaseORMTableUser(rorm.Model, table=True):
34
40
  update_time: rorm.Datetime = rorm.Field(field_default=':update_time', not_null=True, index_n=True, comment='Record update time.')
35
41
  user_id: int = rorm.Field(rorm.types_mysql.MEDIUMINT(unsigned=True), key_auto=True, comment='User ID.')
36
42
  name: str = rorm.Field(rorm.types.VARCHAR(50), not_null=True, index_u=True, comment='User name.')
37
- password: str
38
- email: rorm.Email
39
- phone: int
40
- head: int
43
+ password: str = rorm.Field(rorm.types.CHAR(60), not_null=True, comment='User password, encrypted with "bcrypt".')
44
+ email: rorm.Email = rorm.Field(rorm.types.VARCHAR(255), index_u=True, comment='User email.')
45
+ phone: str = rorm.Field(rorm.types.CHAR(11), index_u=True, comment='User phone.')
46
+ avatar: int = rorm.Field(rorm.types_mysql.MEDIUMINT(unsigned=True), comment='User avatar file ID.')
41
47
  is_valid: bool = rorm.Field(rorm.types_mysql.TINYINT(unsigned=True), field_default='1', not_null=True, comment='Is the valid.')
42
48
 
43
49
 
@@ -61,13 +67,13 @@ class DatabaseORMTablePerm(rorm.Model, table=True):
61
67
  """
62
68
 
63
69
  __name__ = 'perm'
64
- __comment__ = 'Permission information table.'
70
+ __comment__ = 'API permission information table.'
65
71
  create_time: rorm.Datetime = rorm.Field(field_default=':create_time', not_null=True, index_n=True, comment='Record create time.')
66
72
  update_time: rorm.Datetime = rorm.Field(field_default=':update_time', not_null=True, index_n=True, comment='Record update time.')
67
73
  perm_id: int = rorm.Field(rorm.types_mysql.SMALLINT(unsigned=True), key_auto=True, comment='Permission ID.')
68
74
  name: str = rorm.Field(rorm.types.VARCHAR(50), not_null=True, index_u=True, comment='Permission name.')
69
75
  desc: str = rorm.Field(rorm.types.VARCHAR(500), comment='Permission description.')
70
- code: str
76
+ api: str = rorm.Field(rorm.types.VARCHAR(1000), comment='API resource path regular expression "match" pattern.')
71
77
 
72
78
 
73
79
  class DatabaseORMTableUserRole(rorm.Model, table=True):
@@ -96,13 +102,16 @@ class DatabaseORMTableRolePerm(rorm.Model, table=True):
96
102
  perm_id: int = rorm.Field(rorm.types_mysql.SMALLINT(unsigned=True), key=True, comment='Permission ID.')
97
103
 
98
104
 
99
- def build_file_db() -> None:
105
+ def build_auth_db(engine: DatabaseEngine | DatabaseEngineAsync) -> None:
100
106
  """
101
- Check and build `file` database tables.
107
+ Check and build `auth` database tables.
108
+
109
+ Parameters
110
+ ----------
111
+ db : Database engine instance.
102
112
  """
103
113
 
104
114
  # Set parameter.
105
- engine = ServerConfig.server.db.file
106
115
  database = engine.database
107
116
 
108
117
  ## Table.
@@ -120,110 +129,175 @@ def build_file_db() -> None:
120
129
  'path': 'stats',
121
130
  'items': [
122
131
  {
123
- 'name': 'count',
132
+ 'name': 'user_count',
124
133
  'select': (
125
134
  'SELECT COUNT(1)\n'
126
- f'FROM `{database}`.`info`'
135
+ f'FROM `{database}`.`user`'
127
136
  ),
128
- 'comment': 'File information count.'
137
+ 'comment': 'User information count.'
129
138
  },
130
139
  {
131
- 'name': 'past_day_count',
140
+ 'name': 'role_count',
132
141
  'select': (
133
142
  'SELECT COUNT(1)\n'
134
- f'FROM `{database}`.`info`\n'
135
- 'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) = 0'
143
+ f'FROM `{database}`.`role`'
136
144
  ),
137
- 'comment': 'File information count in the past day.'
145
+ 'comment': 'Role information count.'
138
146
  },
139
147
  {
140
- 'name': 'past_week_count',
148
+ 'name': 'perm_count',
141
149
  'select': (
142
150
  'SELECT COUNT(1)\n'
143
- f'FROM `{database}`.`info`\n'
144
- 'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) <= 6'
151
+ f'FROM `{database}`.`perm`'
145
152
  ),
146
- 'comment': 'File information count in the past week.'
153
+ 'comment': 'Permission information count.'
147
154
  },
148
155
  {
149
- 'name': 'past_month_count',
156
+ 'name': 'user_day_count',
150
157
  'select': (
151
158
  'SELECT COUNT(1)\n'
152
- f'FROM `{database}`.`info`\n'
153
- 'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) <= 29'
159
+ f'FROM `{database}`.`user`\n'
160
+ 'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) = 0'
154
161
  ),
155
- 'comment': 'File information count in the past month.'
162
+ 'comment': 'User information count in the past day.'
156
163
  },
157
164
  {
158
- 'name': 'data_count',
165
+ 'name': 'user_week_count',
159
166
  'select': (
160
167
  'SELECT COUNT(1)\n'
161
- f'FROM `{database}`.`data`'
162
- ),
163
- 'comment': 'File data unique count.'
164
- },
165
- {
166
- 'name': 'total_size',
167
- 'select': (
168
- 'SELECT FORMAT(SUM(`size`), 0)\n'
169
- f'FROM `{database}`.`data`'
170
- ),
171
- 'comment': 'File total byte size.'
172
- },
173
- {
174
- 'name': 'avg_size',
175
- 'select': (
176
- 'SELECT FORMAT(AVG(`size`), 0)\n'
177
- f'FROM `{database}`.`data`'
168
+ f'FROM `{database}`.`user`\n'
169
+ 'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) <= 6'
178
170
  ),
179
- 'comment': 'File average byte size.'
171
+ 'comment': 'User information count in the past week.'
180
172
  },
181
173
  {
182
- 'name': 'max_size',
174
+ 'name': 'user_month_count',
183
175
  'select': (
184
- 'SELECT FORMAT(MAX(`size`), 0)\n'
185
- f'FROM `{database}`.`data`'
176
+ 'SELECT COUNT(1)\n'
177
+ f'FROM `{database}`.`user`\n'
178
+ 'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) <= 29'
186
179
  ),
187
- 'comment': 'File maximum byte size.'
180
+ 'comment': 'User information count in the past month.'
188
181
  },
189
182
  {
190
- 'name': 'last_time',
183
+ 'name': 'user_last_time',
191
184
  'select': (
192
185
  'SELECT MAX(`create_time`)\n'
193
- f'FROM `{database}`.`info`'
186
+ f'FROM `{database}`.`user`'
194
187
  ),
195
- 'comment': 'File last record create time.'
188
+ 'comment': 'User last record create time.'
196
189
  }
197
190
  ]
198
191
  }
199
192
  ]
200
193
 
201
194
  # Build.
202
- engine.sync_engine.build.build(tables=tables, views=views, views_stats=views_stats, skip=True)
195
+ engine.sync_engine.build.build(tables=tables, views_stats=views_stats, skip=True)
203
196
 
204
197
 
205
- file_router = APIRouter()
206
- depend_file_sess = Bind.create_depend_db('file', 'sess')
207
- depend_file_conn = Bind.create_depend_db('file', 'conn')
198
+ auth_router = APIRouter()
199
+ depend_auth_sess = Bind.create_depend_db('auth', 'sess')
200
+ depend_auth_conn = Bind.create_depend_db('auth', 'conn')
208
201
 
209
202
 
210
- @file_router.post('/')
211
- async def upload_file(
212
- file: Bind.File = Bind.forms,
213
- name: str = Bind.forms_n,
214
- note: str = Bind.forms_n,
215
- sess: Bind.Sess = depend_file_sess
216
- ) -> DatabaseORMTableInfo:
203
+ @auth_router.post('/sessions')
204
+ async def create_sessions(
205
+ account: str = Bind.i.body,
206
+ password: str = Bind.i.body,
207
+ account_type: Literal['name', 'email', 'phone'] = Bind.Body('name'),
208
+ conn: Bind.Conn = depend_auth_conn
209
+ ) -> dict:
217
210
  """
218
- Upload file.
211
+ Create session.
219
212
 
220
213
  Parameters
221
214
  ----------
222
- file : File instance.
223
- name : File name.
224
- note : File note.
215
+ account : User account, name or email or phone.
216
+ password : User password.
217
+ account_type : User account type.
225
218
 
226
219
  Returns
227
220
  -------
228
- File information.
229
- """
221
+ JSON with `token`.
222
+ """
223
+
224
+ # Parameter.
225
+ key = ServerConfig.server.api_auth_key
226
+ sess_seconds = ServerConfig.server.api_auth_sess_seconds
227
+
228
+ # Check.
229
+ sql = (
230
+ 'SELECT ANY_VALUE(`create_time`) AS `create_time`,\n'
231
+ ' ANY_VALUE(`update_time`) AS `update_time`,\n'
232
+ ' ANY_VALUE(`user`.`user_id`) AS `user_id`,\n'
233
+ ' ANY_VALUE(`user`.`name`) AS `user_name`,\n'
234
+ ' ANY_VALUE(`password`) AS `password`,\n'
235
+ ' ANY_VALUE(`email`) AS `email`,\n'
236
+ ' ANY_VALUE(`phone`) AS `phone`,\n'
237
+ ' ANY_VALUE(`avatar`) AS `avatar`,\n'
238
+ " GROUP_CONCAT(DISTINCT `role`.`name` SEPARATOR ';') AS `role_names`,\n"
239
+ " GROUP_CONCAT(DISTINCT `perm`.`name` SEPARATOR ';') AS `perm_names`,\n"
240
+ " GROUP_CONCAT(DISTINCT `perm`.`api` SEPARATOR ';') AS `perm_apis`\n"
241
+ 'FROM (\n'
242
+ ' SELECT `create_time`, `update_time`, `user_id`, `password`, `name`, `email`, `phone`, `avatar`\n'
243
+ ' FROM `test`.`user`\n'
244
+ f' WHERE `{account_type}` = :account\n'
245
+ ' LIMIT 1\n'
246
+ ') as `user`\n'
247
+ 'LEFT JOIN (\n'
248
+ ' SELECT `user_id`, `role_id`\n'
249
+ ' FROM `test`.`user_role`\n'
250
+ ') as `user_role`\n'
251
+ 'ON `user_role`.`user_id` = `user`.`user_id`\n'
252
+ 'LEFT JOIN (\n'
253
+ ' SELECT `role_id`, `name`\n'
254
+ ' FROM `test`.`role`\n'
255
+ ') AS `role`\n'
256
+ 'ON `user_role`.`role_id` = `role`.`role_id`\n'
257
+ 'LEFT JOIN (\n'
258
+ ' SELECT `role_id`, `perm_id`\n'
259
+ ' FROM `test`.`role_perm`\n'
260
+ ') as `role_perm`\n'
261
+ 'ON `role_perm`.`role_id` = `role`.`role_id`\n'
262
+ 'LEFT JOIN (\n'
263
+ " SELECT `perm_id`, `name`, CONCAT(`method`, ':', `path`) as `api`\n"
264
+ ' FROM `test`.`perm`\n'
265
+ ') AS `perm`\n'
266
+ 'ON `role_perm`.`perm_id` = `perm`.`perm_id`'
267
+ )
268
+ print(1111111111111)
269
+ result = await conn.execute(
270
+ sql,
271
+ account=account
272
+ )
273
+ print(result.fetchall())
274
+ return {'message': 'ok'}
275
+
276
+ # # Check.
277
+ # table = result.to_table()
278
+ # print(table)
279
+ # if table == []:
280
+ # exit_api(401)
281
+ # json = table[0]
282
+ # if not is_hash_bcrypt(password, json['password']):
283
+ # exit_api(401)
284
+
285
+ # # JWT.
286
+ # now_timestamp_s = now('timestamp_s')
287
+ # json['sub'] = json.pop('user_id')
288
+ # json['iat'] = now_timestamp_s
289
+ # json['nbf'] = now_timestamp_s
290
+ # json['exp'] = now_timestamp_s + sess_seconds
291
+ # json['role_names'] = json['role_names'].split(';')
292
+ # json['perm_names'] = json['perm_names'].split(';')
293
+ # perm_apis: list[str] = json['perm_apis'].split(';')
294
+ # perm_api_dict = {}
295
+ # for perm_api in perm_apis:
296
+ # for method, path in perm_api.split(':', 1):
297
+ # paths: list = perm_api_dict.setdefault(method, [])
298
+ # paths.append(path)
299
+ # json['perm_apis'] = perm_api_dict
300
+ # token = encode_jwt(json, key)
301
+ # data = {'token': token}
302
+ # print(111111, data)
303
+ # return data
reyserver/rbase.py CHANGED
@@ -26,8 +26,7 @@ from fastapi.params import (
26
26
  )
27
27
  from reydb.rconn import DatabaseConnectionAsync
28
28
  from reydb.rorm import DatabaseORMModel, DatabaseORMSessionAsync
29
- from reykit.rwrap import wrap_cache
30
- from reykit.rbase import CoroutineFunctionSimple, Base, Exit, StaticMeta, ConfigMeta, throw
29
+ from reykit.rbase import CoroutineFunctionSimple, Base, Exit, StaticMeta, ConfigMeta, Singleton, throw
31
30
 
32
31
  from . import rserver
33
32
 
@@ -38,7 +37,8 @@ __all__ = (
38
37
  'ServerExit',
39
38
  'ServerExitAPI',
40
39
  'exit_api',
41
- 'ServerBind'
40
+ 'ServerBind',
41
+ 'Bind'
42
42
  )
43
43
 
44
44
 
@@ -91,6 +91,168 @@ def exit_api(code: int = 400, text: str | None = None) -> NoReturn:
91
91
  raise ServerExitAPI(code, text)
92
92
 
93
93
 
94
+ class ServerBindInstance(ServerBase, Singleton):
95
+ """
96
+ Server API bind parameter build instance type.
97
+ """
98
+
99
+
100
+ @property
101
+ def path(self) -> Path:
102
+ """
103
+ Path instance.
104
+ """
105
+
106
+ # Build.
107
+ path = Path()
108
+
109
+ return path
110
+
111
+
112
+ @property
113
+ def query(self) -> Query:
114
+ """
115
+ Query instance.
116
+ """
117
+
118
+ # Build.
119
+ query = Query()
120
+
121
+ return query
122
+
123
+
124
+ @property
125
+ def header(self) -> Header:
126
+ """
127
+ Header instance.
128
+ """
129
+
130
+ # Build.
131
+ header = Header()
132
+
133
+ return header
134
+
135
+
136
+ @property
137
+ def cookie(self) -> Cookie:
138
+ """
139
+ Cookie instance.
140
+ """
141
+
142
+ # Build.
143
+ cookie = Cookie()
144
+
145
+ return cookie
146
+
147
+
148
+ @property
149
+ def body(self) -> Body:
150
+ """
151
+ Body instance.
152
+ """
153
+
154
+ # Build.
155
+ body = Body()
156
+
157
+ return body
158
+
159
+
160
+ @property
161
+ def form(self) -> Form:
162
+ """
163
+ Form instance.
164
+ """
165
+
166
+ # Build.
167
+ form = Form()
168
+
169
+ return form
170
+
171
+
172
+ @property
173
+ def forms(self) -> Forms:
174
+ """
175
+ Forms instance.
176
+ """
177
+
178
+ # Build.
179
+ forms = Forms()
180
+
181
+ return forms
182
+
183
+
184
+ @property
185
+ def query_n(self) -> Query:
186
+ """
187
+ Query instance, default `None`.
188
+ """
189
+
190
+ # Build.
191
+ query = Query(None)
192
+
193
+ return query
194
+
195
+
196
+ @property
197
+ def header_n(self) -> Header:
198
+ """
199
+ Header instance, default `None`.
200
+ """
201
+
202
+ # Build.
203
+ header = Header(None)
204
+
205
+ return header
206
+
207
+
208
+ @property
209
+ def cookie_n(self) -> Cookie:
210
+ """
211
+ Cookie instance, default `None`.
212
+ """
213
+
214
+ # Build.
215
+ cookie = Cookie(None)
216
+
217
+ return cookie
218
+
219
+
220
+ @property
221
+ def body_n(self) -> Body:
222
+ """
223
+ Body instance, default `None`.
224
+ """
225
+
226
+ # Build.
227
+ body = Body(None)
228
+
229
+ return body
230
+
231
+
232
+ @property
233
+ def form_n(self) -> Form:
234
+ """
235
+ Form instance, default `None`.
236
+ """
237
+
238
+ # Build.
239
+ form = Form(None)
240
+
241
+ return form
242
+
243
+
244
+ @property
245
+ def forms_n(self) -> Forms:
246
+ """
247
+ Forms instance, default `None`.
248
+ """
249
+
250
+ # Build.
251
+ forms = Forms(None)
252
+
253
+ return forms
254
+
255
+
94
256
  class ServerBind(ServerBase, metaclass=StaticMeta):
95
257
  """
96
258
  Server API bind parameter type.
@@ -148,7 +310,6 @@ class ServerBind(ServerBase, metaclass=StaticMeta):
148
310
  return lifespan
149
311
 
150
312
 
151
- @wrap_cache
152
313
  def create_depend_db(database: str, mode: Literal['sess', 'conn']) -> Depends:
153
314
  """
154
315
  Create dependencie type of asynchronous database.
@@ -201,32 +362,7 @@ class ServerBind(ServerBase, metaclass=StaticMeta):
201
362
  JSON = DatabaseORMModel
202
363
  Conn = DatabaseConnectionAsync
203
364
  Sess = DatabaseORMSessionAsync
204
- path = Path()
205
- 'Path instance.'
206
- query = Query()
207
- 'Query instance.'
208
- header = Header()
209
- 'Header instance.'
210
- cookie = Cookie()
211
- 'Cookie instance.'
212
- body = Body()
213
- 'Body instance.'
214
- form = Form()
215
- 'Form instance.'
216
- forms = Forms()
217
- 'Forms instance.'
218
- query_n = Query(None)
219
- 'Query instance, default `None`.'
220
- header_n = Header(None)
221
- 'Header instance, default `None`.'
222
- cookie_n = Cookie(None)
223
- 'Cookie instance, default `None`.'
224
- body_n = Body(None)
225
- 'Body instance, default `None`.'
226
- form_n = Form(None)
227
- 'Form instance, default `None`.'
228
- forms_n = Forms(None)
229
- 'Forms instance, default `None`.'
365
+ i = ServerBindInstance()
230
366
 
231
367
 
232
368
  Bind = ServerBind
reyserver/rclient.py CHANGED
@@ -9,7 +9,7 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import TypedDict
12
+ from typing import TypedDict, Literal
13
13
  from datetime import datetime as Datetime
14
14
  from reykit.ros import File, Folder, overload
15
15
  from reykit.rnet import join_url, request, get_response_file_name
@@ -44,6 +44,43 @@ class ServerClient(ServerBase):
44
44
  self.url = url
45
45
 
46
46
 
47
+ def create_session(
48
+ self,
49
+ account: str,
50
+ password: str,
51
+ account_type: Literal['name', 'email', 'phone'] = 'name'
52
+ ) -> str:
53
+ """
54
+ Create session.
55
+
56
+ Parameters
57
+ ----------
58
+ account : User account, name or email or phone.
59
+ password : User password.
60
+ account_type : User account type.
61
+
62
+ Returns
63
+ -------
64
+ Token.
65
+ """
66
+
67
+ # Parameter.
68
+ url = join_url(self.url, 'sessions')
69
+ json = {
70
+ 'account': account,
71
+ 'password': password,
72
+ 'account_type': account_type
73
+ }
74
+
75
+ # Request.
76
+ response = request(url, json=json, check=True)
77
+ response_dict = response.json()
78
+ print(response_dict)
79
+ token = response_dict['token']
80
+
81
+ return token
82
+
83
+
47
84
  def upload_file(
48
85
  self,
49
86
  source: str | bytes,
reyserver/rfile.py CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  from fastapi import APIRouter
13
13
  from fastapi.responses import FileResponse
14
- from reydb import rorm
14
+ from reydb import rorm, DatabaseEngine, DatabaseEngineAsync
15
15
  from reykit.ros import FileStore, get_md5
16
16
 
17
17
  from .rbase import ServerConfig, Bind, exit_api
@@ -51,13 +51,16 @@ class DatabaseORMTableData(rorm.Model, table=True):
51
51
  path: str = rorm.Field(rorm.types.VARCHAR(4095), not_null=True, comment='File disk storage path.')
52
52
 
53
53
 
54
- def build_file_db() -> None:
54
+ def build_file_db(engine: DatabaseEngine | DatabaseEngineAsync) -> None:
55
55
  """
56
56
  Check and build `file` database tables.
57
+
58
+ Parameters
59
+ ----------
60
+ db : Database engine instance.
57
61
  """
58
62
 
59
63
  # Set parameter.
60
- engine = ServerConfig.server.db.file
61
64
  database = engine.database
62
65
 
63
66
  ## Table.
@@ -179,11 +182,38 @@ depend_file_sess = Bind.create_depend_db('file', 'sess')
179
182
  depend_file_conn = Bind.create_depend_db('file', 'conn')
180
183
 
181
184
 
182
- @file_router.post('/')
185
+ @file_router.get('/files/{file_id}')
186
+ async def get_file_info(
187
+ file_id: int = Bind.i.path,
188
+ sess: Bind.Sess = depend_file_sess
189
+ ) -> DatabaseORMTableInfo:
190
+ """
191
+ Get file information.
192
+
193
+ Parameters
194
+ ----------
195
+ file_id : File ID.
196
+
197
+ Returns
198
+ -------
199
+ File information.
200
+ """
201
+
202
+ # Get.
203
+ table_info = await sess.get(DatabaseORMTableInfo, file_id)
204
+
205
+ # Check.
206
+ if table_info is None:
207
+ exit_api(404)
208
+
209
+ return table_info
210
+
211
+
212
+ @file_router.post('/files')
183
213
  async def upload_file(
184
- file: Bind.File = Bind.forms,
185
- name: str = Bind.forms_n,
186
- note: str = Bind.forms_n,
214
+ file: Bind.File = Bind.i.forms,
215
+ name: str = Bind.i.forms_n,
216
+ note: str = Bind.i.forms_n,
187
217
  sess: Bind.Sess = depend_file_sess
188
218
  ) -> DatabaseORMTableInfo:
189
219
  """
@@ -233,9 +263,9 @@ async def upload_file(
233
263
  return table_info
234
264
 
235
265
 
236
- @file_router.get('/{file_id}/download')
266
+ @file_router.get('/files/{file_id}/download')
237
267
  async def download_file(
238
- file_id: int = Bind.path,
268
+ file_id: int = Bind.i.path,
239
269
  conn: Bind.Conn = depend_file_conn
240
270
  ) -> FileResponse:
241
271
  """
@@ -273,30 +303,3 @@ async def download_file(
273
303
  response = FileResponse(file_path, filename=file_name)
274
304
 
275
305
  return response
276
-
277
-
278
- @file_router.get('/{file_id}')
279
- async def get_file_info(
280
- file_id: int = Bind.path,
281
- sess: Bind.Sess = depend_file_sess
282
- ) -> DatabaseORMTableInfo:
283
- """
284
- Get file information.
285
-
286
- Parameters
287
- ----------
288
- file_id : File ID.
289
-
290
- Returns
291
- -------
292
- File information.
293
- """
294
-
295
- # Get.
296
- table_info = await sess.get(DatabaseORMTableInfo, file_id)
297
-
298
- # Check.
299
- if table_info is None:
300
- exit_api(404)
301
-
302
- return table_info
reyserver/rserver.py CHANGED
@@ -19,7 +19,8 @@ from fastapi.staticfiles import StaticFiles
19
19
  from fastapi.middleware.gzip import GZipMiddleware
20
20
  from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
21
21
  from reydb import DatabaseAsync
22
- from reykit.rbase import CallableT, CoroutineFunctionSimple, Singleton, throw
22
+ from reykit.rbase import CoroutineFunctionSimple, Singleton, throw
23
+ from reykit.rrand import randchar
23
24
 
24
25
  from .rbase import ServerBase, ServerConfig, Bind
25
26
 
@@ -102,6 +103,10 @@ class Server(ServerBase, Singleton):
102
103
  self.__add_default_middleware()
103
104
 
104
105
  # API.
106
+ self.api_auth_key: str
107
+ 'Authentication API JWT encryption key.'
108
+ self.api_auth_sess_seconds: int
109
+ 'Authentication API session valid seconds.'
105
110
  self.api_file_dir: str
106
111
  'File API store directory path.'
107
112
 
@@ -187,13 +192,32 @@ class Server(ServerBase, Singleton):
187
192
  setattr(self.app, key, value)
188
193
 
189
194
 
190
- def add_api_auth(self):
195
+ def add_api_auth(self, key: str | None = None, sess_seconds: int = 28800) -> None:
191
196
  """
192
- Add Authentication API.
197
+ Add authentication API.
193
198
  Note: must include database engine of `auth` name.
199
+
200
+ Parameters
201
+ ----------
202
+ key : JWT encryption key.
203
+ - `None`: Random 32 length string.
204
+ sess_seconds : Session valid seconds.
194
205
  """
195
206
 
196
- ...
207
+ from .rauth import build_auth_db, auth_router
208
+
209
+ # Parameter.
210
+ if key is None:
211
+ key = randchar(32)
212
+
213
+ # Build database.
214
+ engine = self.db.auth
215
+ build_auth_db(engine)
216
+
217
+ # Add.
218
+ self.api_auth_key = key
219
+ self.api_auth_sess_seconds = sess_seconds
220
+ self.app.include_router(auth_router, tags=['auth'])
197
221
 
198
222
 
199
223
  def add_api_file(self, file_dir: str = 'file') -> None:
@@ -207,11 +231,12 @@ class Server(ServerBase, Singleton):
207
231
  prefix : File API path prefix.
208
232
  """
209
233
 
210
- from .rfile import file_router, build_file_db
234
+ from .rfile import build_file_db, file_router
211
235
 
212
236
  # Build database.
213
- build_file_db()
237
+ engine = self.db.file
238
+ build_file_db(engine)
214
239
 
215
240
  # Add.
216
241
  self.api_file_dir = file_dir
217
- self.app.include_router(file_router, prefix='/files', tags=['file'])
242
+ self.app.include_router(file_router, tags=['file'])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reyserver
3
- Version: 1.1.49
3
+ Version: 1.1.51
4
4
  Summary: Backend server method set.
5
5
  Project-URL: homepage, https://github.com/reyxbo/reyserver/
6
6
  Author-email: Rey <reyxbo@163.com>
@@ -0,0 +1,11 @@
1
+ reyserver/__init__.py,sha256=7GX64p7uI2eetJH9NJ-DTg-8iyQwOsGcviADFJCPxVA,373
2
+ reyserver/rall.py,sha256=riyDRTUsigco_Bee1H4aZFb8IgvjnxdX9qcnVb9i9mE,270
3
+ reyserver/rauth.py,sha256=T2oafUAmXr4WfVYmEHO5v0j9K703KUYLGNVEom0J76Q,11716
4
+ reyserver/rbase.py,sha256=xgdLP_O77e-pSrRWm9GVSziPSqEOh2w20cWkF4HBeWo,7042
5
+ reyserver/rclient.py,sha256=IWZ3smyIP0_YJrfSrM8JFCr0FCtN02AyT3hp8YuSsDQ,5103
6
+ reyserver/rfile.py,sha256=bvuXOYO3UDM1jMiyNzQDz56_0ekZUEIRcfNFAhGgdUY,9010
7
+ reyserver/rserver.py,sha256=gOvLfaLqiDgHcZbzd3h2iIaDtraCuBcmsy1d61TaJ2c,6717
8
+ reyserver-1.1.51.dist-info/METADATA,sha256=F4eENaUB_2lE1aEeV4ZZ_W7AHW7iB6NfPuTsR1fy-8U,1689
9
+ reyserver-1.1.51.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
+ reyserver-1.1.51.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
11
+ reyserver-1.1.51.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- reyserver/__init__.py,sha256=7GX64p7uI2eetJH9NJ-DTg-8iyQwOsGcviADFJCPxVA,373
2
- reyserver/rall.py,sha256=riyDRTUsigco_Bee1H4aZFb8IgvjnxdX9qcnVb9i9mE,270
3
- reyserver/rauth.py,sha256=VC6Gq2uoiQuON4pmSueZojucU4m2FTdPxLPhGgM4G0A,8390
4
- reyserver/rbase.py,sha256=IUVkkNsLmQh-QRLX6qtbCjPZAbQAsxoe0goPLCxG9KA,5283
5
- reyserver/rclient.py,sha256=pTJtn78jPKgFo5EoQwZRdM0cYHdCs7QUKqfl-jUBRgk,4220
6
- reyserver/rfile.py,sha256=C_kuH9KQS6E5VFDmg_dvbEYfyWxa1hl64fjoh8BFiXQ,8874
7
- reyserver/rserver.py,sha256=hqpemzJHO6xHy_7pO3cvvjnfy8Yfqy8HfyIq4sjk4Dc,5889
8
- reyserver-1.1.49.dist-info/METADATA,sha256=LnFaa55uE9AkN95GWcvdVCPyIjQjw9S-xh3OE7QOLlo,1689
9
- reyserver-1.1.49.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
- reyserver-1.1.49.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
11
- reyserver-1.1.49.dist-info/RECORD,,