WIP auth, added Drift for database and refined shared_models for data exchange
This commit is contained in:
parent
d39e119bf4
commit
37e168e46b
@ -4,6 +4,8 @@ linter:
|
||||
file_names: false
|
||||
camel_case_types: true
|
||||
prefer_single_quotes: true
|
||||
public_member_api_docs: false
|
||||
lines_longer_than_80_chars: false
|
||||
|
||||
analyzer:
|
||||
exclude:
|
||||
|
14
backend/build.yaml
Normal file
14
backend/build.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
targets:
|
||||
$default:
|
||||
builders:
|
||||
drift_dev:
|
||||
options:
|
||||
# The directory where the test files are stored:
|
||||
test_dir: drift/test/ # (default)
|
||||
# The directory where the schema files are stored:
|
||||
schema_dir: drift/schemas/ # (default)
|
||||
databases:
|
||||
db: lib/database.dart
|
||||
# Optional: Add more databases
|
||||
# another_db: lib/database2.dart
|
||||
|
49
backend/lib/authenticator.dart
Normal file
49
backend/lib/authenticator.dart
Normal file
@ -0,0 +1,49 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:backend/database.dart';
|
||||
import 'package:backend/service/db_access.dart';
|
||||
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
|
||||
|
||||
final jwtSecret = _getSecret();
|
||||
|
||||
class Authenticator {
|
||||
Future<String?> generateToken({required String username}) async {
|
||||
final newUser = await Db.createUser(username: username);
|
||||
if (newUser == null) return null;
|
||||
|
||||
final jwt = JWT(
|
||||
{
|
||||
'uid': newUser.uuid,
|
||||
},
|
||||
);
|
||||
|
||||
return jwt.sign(SecretKey(jwtSecret));
|
||||
}
|
||||
|
||||
Future<User?> verifyToken(
|
||||
String token,
|
||||
) async {
|
||||
try {
|
||||
final payload = JWT.verify(
|
||||
token,
|
||||
SecretKey(jwtSecret),
|
||||
);
|
||||
|
||||
final payloadData = payload.payload as Map<String, dynamic>;
|
||||
|
||||
final uuid = payloadData['uuid'] as String;
|
||||
return await Db.getUser(uuid);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String _getSecret() {
|
||||
final secret = Platform.environment['JWT_TOKEN_SECRET'];
|
||||
if (secret == null || secret.isEmpty) {
|
||||
throw Exception('JWT secret not configured. Define JWT_TOKEN_SECRET in environment.');
|
||||
} else {
|
||||
return secret;
|
||||
}
|
||||
}
|
53
backend/lib/database.dart
Normal file
53
backend/lib/database.dart
Normal file
@ -0,0 +1,53 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
|
||||
part 'database.g.dart';
|
||||
|
||||
class Users extends Table {
|
||||
TextColumn get uuid => text().unique()();
|
||||
TextColumn get gameRoom => text().references(GameRooms, #uuid).nullable()();
|
||||
TextColumn get name => text().withLength(min: 2, max: 32)();
|
||||
DateTimeColumn get createdAt => dateTime().nullable()();
|
||||
}
|
||||
|
||||
enum GameStatus {
|
||||
opened,
|
||||
running,
|
||||
closed,
|
||||
}
|
||||
|
||||
class GameRooms extends Table {
|
||||
TextColumn get uuid => text().unique()();
|
||||
TextColumn get status => textEnum<GameStatus>()();
|
||||
DateTimeColumn get createdAt => dateTime().nullable()();
|
||||
}
|
||||
|
||||
@DriftDatabase(tables: [Users, GameRooms])
|
||||
class AppDatabase extends _$AppDatabase {
|
||||
AppDatabase() : super(_openConnection());
|
||||
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
|
||||
static QueryExecutor _openConnection() {
|
||||
return NativeDatabase.createInBackground(File('./backend.db'));
|
||||
}
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration {
|
||||
return MigrationStrategy(
|
||||
beforeOpen: (details) async {
|
||||
// Statements to run to make sqlite performant, running in WAL mode, etc
|
||||
await customStatement('PRAGMA foreign_keys = ON');
|
||||
await customStatement('PRAGMA journal_mode=WAL');
|
||||
await customStatement('PRAGMA busy_timeout=5000');
|
||||
await customStatement('PRAGMA synchronous=NORMAL');
|
||||
await customStatement('PRAGMA cache_size=10000');
|
||||
await customStatement('PRAGMA temp_store=MEMORY');
|
||||
await customStatement('PRAGMA mmap_size=268435456');
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
24
backend/lib/service/db_access.dart
Normal file
24
backend/lib/service/db_access.dart
Normal file
@ -0,0 +1,24 @@
|
||||
import 'package:backend/database.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
final log = Logger('Db');
|
||||
|
||||
class Db {
|
||||
static Future<User> getUser(String uuid) {
|
||||
log.finer('Getting user $uuid');
|
||||
return AppDatabase().managers.users.filter((f) => f.uuid.equals(uuid)).get().then((u) => u.first);
|
||||
}
|
||||
|
||||
static Future<User?> createUser({required String username}) => AppDatabase()
|
||||
.managers
|
||||
.users
|
||||
.createReturningOrNull(
|
||||
(o) => o(createdAt: Value(DateTime.now()), uuid: const Uuid().v4(), name: username),
|
||||
)
|
||||
.catchError((Object err) {
|
||||
log.severe('Failed to create user', err, StackTrace.current);
|
||||
throw Exception(err.toString());
|
||||
});
|
||||
}
|
17
backend/main.dart
Normal file
17
backend/main.dart
Normal file
@ -0,0 +1,17 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dart_frog/dart_frog.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
Future<HttpServer> run(Handler handler, InternetAddress ip, int port) {
|
||||
// 1. Execute any custom code prior to starting the server...
|
||||
|
||||
final String logLevel = Platform.environment['LOG_LEVEL'] ?? 'INFO';
|
||||
Logger.root.level =
|
||||
Level.LEVELS.firstWhere((l) => l.name == logLevel, orElse: () => Level.INFO); // defaults to Level.INFO
|
||||
Logger.root.onRecord.listen((record) {
|
||||
stdout.writeln('${record.level.name}: ${record.time}: ${record.message}');
|
||||
});
|
||||
|
||||
return serve(handler, ip, port);
|
||||
}
|
@ -14,6 +14,14 @@ packages:
|
||||
description: dart
|
||||
source: sdk
|
||||
version: "0.3.3"
|
||||
adaptive_number:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: adaptive_number
|
||||
sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -46,6 +54,110 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
build:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build
|
||||
sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
sha256: "294a2edaf4814a378725bfe6358210196f5ea37af89ecd81bfa32960113d4948"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.3"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.14"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.0"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.9.3"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.10.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -86,6 +198,62 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
dart_frog_auth:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dart_frog_auth
|
||||
sha256: a4c05e6764a82f8997dee9fb68661a473afea92527a2dd8a6677e5a1b454b463
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
dart_jsonwebtoken:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dart_jsonwebtoken
|
||||
sha256: "06e02e18827d047f206e1051c15b493c9c29a2dba0f9b2a905d73748dec4f931"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.16.0"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
drift:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: drift
|
||||
sha256: "76f23535e19a9f2be92f954e74d8802e96f526e5195d7408c1a20f6659043941"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.24.0"
|
||||
drift_dev:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: drift_dev
|
||||
sha256: d1d90b0d55b22de412b77186f3bf3179a4b7e2acc4c8fb3a7aaf28a01abc194b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.24.0"
|
||||
ed25519_edwards:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ed25519_edwards
|
||||
sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -94,6 +262,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -110,6 +286,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
hotreloader:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -158,8 +342,16 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.1"
|
||||
logging:
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logging
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
@ -230,6 +422,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.9.1"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -246,6 +446,29 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
recase:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: recase
|
||||
sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
shared_models:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../shared_models"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -286,6 +509,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_gen
|
||||
sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -310,6 +541,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sprintf
|
||||
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
sqlite3:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sqlite3
|
||||
sha256: "35d3726fe18ab1463403a5cc8d97dbc81f2a0b08082e8173851363fcc97b6627"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.2"
|
||||
sqlparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqlparser
|
||||
sha256: "27dd0a9f0c02e22ac0eb42a23df9ea079ce69b52bb4a3b478d64e0ef34a263ee"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.41.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -374,6 +629,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.8"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -382,6 +645,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
uuid:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: uuid
|
||||
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.1"
|
||||
very_good_analysis:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@ -447,4 +718,4 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.5.0 <4.0.0"
|
||||
dart: ">=3.6.0 <4.0.0"
|
||||
|
@ -8,10 +8,18 @@ environment:
|
||||
|
||||
dependencies:
|
||||
dart_frog: ^1.1.0
|
||||
dart_frog_auth: ^1.2.0
|
||||
dart_jsonwebtoken: ^2.16.0
|
||||
drift: ^2.24.0
|
||||
logging: ^1.3.0
|
||||
shared_models:
|
||||
path: ../shared_models
|
||||
sqlite3: ^2.7.2
|
||||
uuid: ^4.5.1
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.14
|
||||
drift_dev: ^2.24.0
|
||||
mocktail: ^1.0.3
|
||||
test: ^1.25.5
|
||||
very_good_analysis: ^5.1.0
|
||||
|
17
backend/routes/[roomCode]/_middleware.dart
Normal file
17
backend/routes/[roomCode]/_middleware.dart
Normal file
@ -0,0 +1,17 @@
|
||||
import 'package:backend/authenticator.dart';
|
||||
import 'package:backend/database.dart';
|
||||
import 'package:dart_frog/dart_frog.dart';
|
||||
import 'package:dart_frog_auth/dart_frog_auth.dart';
|
||||
|
||||
Handler middleware(Handler handler) {
|
||||
return handler.use(
|
||||
bearerAuthentication<User>(
|
||||
authenticator: (context, token) async {
|
||||
final authenticator = context.read<Authenticator>();
|
||||
return authenticator.verifyToken(token);
|
||||
},
|
||||
// says to apply the middleware to all routes
|
||||
applies: (_) async => true,
|
||||
),
|
||||
);
|
||||
}
|
5
backend/routes/[roomCode]/join.dart
Normal file
5
backend/routes/[roomCode]/join.dart
Normal file
@ -0,0 +1,5 @@
|
||||
import 'package:dart_frog/dart_frog.dart';
|
||||
|
||||
Response onRequest(RequestContext context, String roomCode) {
|
||||
return Response(body: 'Joined $roomCode!');
|
||||
}
|
15
backend/routes/_middleware.dart
Normal file
15
backend/routes/_middleware.dart
Normal file
@ -0,0 +1,15 @@
|
||||
// lib/routes/tasks/_middleware.dart
|
||||
import 'package:dart_frog/dart_frog.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
final log = Logger('');
|
||||
|
||||
Handler middleware(Handler handler) {
|
||||
return handler.use(
|
||||
(handler) => (context) async {
|
||||
final request = context.request;
|
||||
log.info('${request.method.value} ${request.uri.path}');
|
||||
return await handler(context);
|
||||
},
|
||||
);
|
||||
}
|
45
backend/routes/auth/index.dart
Normal file
45
backend/routes/auth/index.dart
Normal file
@ -0,0 +1,45 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:backend/authenticator.dart';
|
||||
import 'package:dart_frog/dart_frog.dart';
|
||||
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
|
||||
import 'package:shared_models/user.dart';
|
||||
|
||||
Future<Response> onRequest(RequestContext context) async {
|
||||
// Only allow POST requests
|
||||
if (context.request.method != HttpMethod.post) {
|
||||
return Response(statusCode: HttpStatus.methodNotAllowed);
|
||||
}
|
||||
|
||||
try {
|
||||
// Parse the request body
|
||||
final body = await context.request.json() as Map<String, dynamic>;
|
||||
final createUserReq = CreateUserRequest.fromJson(body);
|
||||
|
||||
// Generate token
|
||||
final authenticator = context.read<Authenticator>();
|
||||
final token = await authenticator.generateToken(username: createUserReq.username);
|
||||
|
||||
if (token == null) {
|
||||
return Response.json(
|
||||
statusCode: HttpStatus.internalServerError,
|
||||
body: {'error': 'Failed to generate token'},
|
||||
);
|
||||
}
|
||||
|
||||
// Return the token
|
||||
return Response.json(
|
||||
body: {'token': token},
|
||||
);
|
||||
} on JWTParseException {
|
||||
return Response.json(
|
||||
statusCode: HttpStatus.badRequest,
|
||||
body: {'error': 'Username is required'},
|
||||
);
|
||||
} catch (e) {
|
||||
return Response.json(
|
||||
statusCode: HttpStatus.internalServerError,
|
||||
body: {'error': 'Internal server error'},
|
||||
);
|
||||
}
|
||||
}
|
31
shared_models/lib/user.dart
Normal file
31
shared_models/lib/user.dart
Normal file
@ -0,0 +1,31 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'user.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class User {
|
||||
final String id;
|
||||
final String name;
|
||||
final String? roomId;
|
||||
|
||||
User({
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.roomId,
|
||||
});
|
||||
|
||||
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$UserToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class CreateUserRequest {
|
||||
final String username;
|
||||
|
||||
CreateUserRequest({required this.username});
|
||||
|
||||
factory CreateUserRequest.fromJson(Map<String, dynamic> json) => _$CreateUserRequestFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$CreateUserRequestToJson(this);
|
||||
}
|
@ -62,6 +62,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
sha256: "294a2edaf4814a378725bfe6358210196f5ea37af89ecd81bfa32960113d4948"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.3"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.14"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.0"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: "28a712df2576b63c6c005c465989a348604960c0958d28be5303ba9baa841ac2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.9.3"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -70,6 +118,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.10.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -118,6 +174,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -134,6 +198,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -366,6 +438,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_transform
|
||||
sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -406,6 +486,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.8"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -11,5 +11,6 @@ dependencies:
|
||||
|
||||
dev_dependencies:
|
||||
json_serializable: ^6.9.3
|
||||
build_runner: ^2.4.14
|
||||
lints: ^5.0.0
|
||||
test: ^1.24.0
|
||||
|
Loading…
Reference in New Issue
Block a user