Compare commits

..

45 commits

Author SHA1 Message Date
424e9b7b02
Always restart 2025-08-23 10:39:49 -04:00
a48c2fcd42
add max age 2025-08-18 14:14:30 -04:00
ff95c70961
Change launch name 2025-08-01 16:23:56 -04:00
3703c97e09
Add nickname 2025-07-30 12:22:31 -04:00
a5c4f900a2
Trim name 2025-07-27 15:53:06 -04:00
8cb223e862
Change naming 2025-07-27 15:29:43 -04:00
644d065ec9
Add fake name fields 2025-07-27 15:13:17 -04:00
a86c8e2b26
Add name to userinfo 2025-07-26 10:08:10 -04:00
957a6c6c97
Trim files 2025-07-25 19:51:10 -04:00
864fcad631
simplify 2025-07-25 12:24:38 -04:00
55bd5b934b
rm email 2025-07-25 12:24:22 -04:00
43f59851b8
Some fixes 2025-07-22 14:15:13 -04:00
afc555e66e
Fix name 2025-07-22 13:51:10 -04:00
444fff5b62
Add more info to introspection 2025-07-22 11:46:38 -04:00
c7a014f0b3
add nonce 2025-07-22 10:30:15 -04:00
05e1a4aab1
Add nonce support 2025-07-21 21:43:04 -04:00
43ad7937f9
Use double quotes 2025-07-20 16:31:03 -04:00
53867e273b
Add introspection endpoint 2025-07-20 16:27:53 -04:00
8efb087cdd
Add dummy logout endpoint 2025-07-20 15:47:52 -04:00
53df67a4ce
Add name field 2025-07-20 14:34:24 -04:00
8e2df0703d
Add email 2025-07-20 14:29:03 -04:00
13a469ba6d
serviceDomain mandatory 2025-06-22 15:30:51 -04:00
0dfc6c96ee
Use cookie 2025-06-22 15:17:07 -04:00
fb298c9880
Don't trim 2025-06-22 14:50:24 -04:00
32ec721e23
try to toString 2025-06-22 14:15:53 -04:00
a27a53b2cf
wait is this actually working 2025-06-22 14:06:06 -04:00
754ff56119
Attempt fix 2025-06-22 13:09:28 -04:00
b7bd137e16
add bridge 2025-06-22 12:52:42 -04:00
7d729ccb76
Trim secret 2025-06-22 04:01:58 -04:00
a19b5e1bfb
rm test print 2025-06-21 20:14:30 -04:00
a3733511b6
rm jwk stuff 2025-06-21 20:06:09 -04:00
f875ef4071
rm netlink 2025-06-20 15:07:34 -04:00
9ce1196be1
Quick fix for forgejo 2025-06-20 14:26:21 -04:00
e1941308ca
Fix test 2025-06-20 14:12:47 -04:00
f076bd496f
Change UMask 2025-06-20 14:07:23 -04:00
e707ac44e2
no private users 2025-06-20 14:02:21 -04:00
b8394734d2
Add AF_UNIX 2025-06-20 13:38:45 -04:00
6a4c86d436
RM help 2025-06-20 10:15:45 -04:00
e07331f052
Use array for args 2025-06-20 10:09:12 -04:00
461e5bdfcf
Dont use deprecated types 2025-06-20 09:41:34 -04:00
766ce5fc8c
Fix group 2025-06-20 09:39:09 -04:00
40e61e08f8
Move out of perSystem 2025-06-20 09:26:53 -04:00
3ff78be71a
try to fix package 2025-06-19 22:21:57 -04:00
f04d073e6b
Add flake, module 2025-06-19 22:15:05 -04:00
680d7fcd05
slight changes 2025-06-19 17:33:50 -04:00
16 changed files with 1164 additions and 85 deletions

4
.vscode/launch.json vendored
View file

@ -5,7 +5,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "matrix-oauth2oidc", "name": "matrixoidc",
"program": "bin/matrixoidc.dart", "program": "bin/matrixoidc.dart",
"args": [ "args": [
"--homeserver", "--homeserver",
@ -13,7 +13,7 @@
"--jwtSecretFile", "--jwtSecretFile",
"secret", "secret",
"--issuer", "--issuer",
"http://localhost:8080/", "http://localhost:8080",
"--authorizeEndpoint", "--authorizeEndpoint",
"http://localhost:4321/login", "http://localhost:4321/login",
"--serviceDomain", "--serviceDomain",

View file

@ -5,4 +5,4 @@ build:
dart run build_runner build dart run build_runner build
test: test:
oauth2c http://localhost:8080 --client-id yourclientid --redirect-url http://localhost/callback --scopes openid --grant-type authorization_code --auth-method none --response-mode query oauth2c http://localhost:8080 --client-id yourclientid --scopes openid --grant-type authorization_code --auth-method none --response-mode query

View file

@ -1,5 +1,5 @@
import "dart:io"; import "dart:io";
import "package:args/args.dart"; import "package:cli_tools/config.dart";
import "package:matrixoidc/controllers/settings_controller.dart"; import "package:matrixoidc/controllers/settings_controller.dart";
import "package:matrixoidc/helpers/api_helper.dart"; import "package:matrixoidc/helpers/api_helper.dart";
import "package:riverpod/riverpod.dart"; import "package:riverpod/riverpod.dart";
@ -8,18 +8,17 @@ import "package:shelf/shelf_io.dart";
import "package:shelf_router/shelf_router.dart"; import "package:shelf_router/shelf_router.dart";
void main(List<String> argsRaw) async { void main(List<String> argsRaw) async {
final parser = ArgParser() final parser = ConfigParser()
..addOption("socket", abbr: "s") ..addOption("socket", abbr: "s")
..addOption("serviceDomain", abbr: "d")
..addOption("port", abbr: "p", defaultsTo: "8080") ..addOption("port", abbr: "p", defaultsTo: "8080")
..addOption("address", abbr: "a", defaultsTo: "127.0.0.1") ..addOption("address", abbr: "a", defaultsTo: "127.0.0.1")
..addOption("issuer", abbr: "i", mandatory: true) ..addOption("issuer", abbr: "i", mandatory: true)
..addOption("homeserver", abbr: "h", mandatory: true) ..addOption("homeserver", abbr: "u", mandatory: true)
..addOption("serviceDomain", abbr: "d", mandatory: true)
..addOption("jwtSecretFile", abbr: "j", mandatory: true) ..addOption("jwtSecretFile", abbr: "j", mandatory: true)
..addOption("authorizeEndpoint", abbr: "e", mandatory: true); ..addOption("authorizeEndpoint", abbr: "e", mandatory: true);
final container = ProviderContainer(); final container = ProviderContainer();
container container
.read(SettingsController.provider.notifier) .read(SettingsController.provider.notifier)
.set(parser.parse(argsRaw)); .set(parser.parse(argsRaw));
@ -35,8 +34,9 @@ void main(List<String> argsRaw) async {
apiHelper.openidConfiguration, apiHelper.openidConfiguration,
) )
..get("/userinfo", apiHelper.userinfoHandler) ..get("/userinfo", apiHelper.userinfoHandler)
..get("/jwks.json", apiHelper.jwks) ..get("/bridge", apiHelper.bridgeHandler)
..post("/login", apiHelper.handleLogin) ..post("/login", apiHelper.loginHandler)
..post("/logout", apiHelper.logoutHandler)
..post("/token", apiHelper.tokenHandler)) ..post("/token", apiHelper.tokenHandler))
.call, .call,
); );

View file

@ -4,24 +4,40 @@
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
}; };
outputs = { outputs = inputs:
flake-parts, inputs.flake-parts.lib.mkFlake {inherit inputs;} {
nixpkgs,
self,
...
} @ inputs:
flake-parts.lib.mkFlake {inherit inputs;} {
systems = ["x86_64-linux" "aarch64-linux"]; systems = ["x86_64-linux" "aarch64-linux"];
perSystem = { perSystem = {
lib,
pkgs, pkgs,
system, system,
... ...
}: { }: {
_module.args.pkgs = import nixpkgs {inherit system;}; _module.args.pkgs = import inputs.nixpkgs {inherit system;};
devShells.default = pkgs.mkShell { devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [just dart oauth2c watchexec]; buildInputs = with pkgs; [just dart oauth2c watchexec];
}; };
packages.default = pkgs.buildDartApplication {
pname = "matrixoidc";
version = "1.0.0";
src = ./.;
dartConfigHook = "packageRun build_runner build";
pubspecLock = lib.importJSON ./pubspec.lock.json;
preInstall = "set -x";
meta = {
homepage = "https://git.federated.nexus/Henry-Hiles/matrixoidc";
description = "An attempt to make an OIDC provider that authenticates with matrix OAuth.";
mainProgram = "matrixoidc";
license = lib.licenses.gpl3Plus;
maintainers = [lib.maintainers.quadradical];
}; };
}; };
};
flake.nixosModules.default = import ./module.nix inputs.self;
};
} }

View file

@ -0,0 +1,18 @@
import "dart:io";
import "package:dart_jsonwebtoken/dart_jsonwebtoken.dart";
import "package:matrixoidc/controllers/settings_controller.dart";
import "package:riverpod/riverpod.dart";
class KeyController extends AsyncNotifier<SecretKey> {
@override
Future<SecretKey> build() async => SecretKey(
(await File.fromUri(
Uri.file(ref.read(SettingsController.provider)!.jwtSecretFile),
).readAsString()).trim(),
);
static final provider = AsyncNotifierProvider<KeyController, SecretKey>(
KeyController.new,
);
}

View file

@ -1,7 +1,7 @@
import "dart:io";
import "dart:convert"; import "dart:convert";
import "package:dart_jsonwebtoken/dart_jsonwebtoken.dart"; import "package:dart_jsonwebtoken/dart_jsonwebtoken.dart";
import "package:matrixoidc/controllers/auth_code_controller.dart"; import "package:matrixoidc/controllers/auth_code_controller.dart";
import "package:matrixoidc/controllers/key_controller.dart";
import "package:matrixoidc/controllers/settings_controller.dart"; import "package:matrixoidc/controllers/settings_controller.dart";
import "package:shelf/shelf.dart"; import "package:shelf/shelf.dart";
import "package:http/http.dart" as http; import "package:http/http.dart" as http;
@ -12,7 +12,7 @@ class ApiHelper {
final Ref ref; final Ref ref;
ApiHelper(this.ref); ApiHelper(this.ref);
Future<Response> handleLogin(Request request) async { Future<Response> loginHandler(Request request) async {
final body = await request.readAsString(); final body = await request.readAsString();
final data = Uri.splitQueryString(body); final data = Uri.splitQueryString(body);
@ -22,7 +22,7 @@ class ApiHelper {
final state = data["state"] ?? ""; final state = data["state"] ?? "";
if (userId == null || accessToken == null || redirectUri == null) { if (userId == null || accessToken == null || redirectUri == null) {
return Response(400, body: "Missing parameters"); return Response(400, body: json.encode({"error": "Missing parameters"}));
} }
final settings = ref.read(SettingsController.provider)!; final settings = ref.read(SettingsController.provider)!;
@ -32,7 +32,9 @@ class ApiHelper {
); );
if (whoamiRes.statusCode != 200) { if (whoamiRes.statusCode != 200) {
return Response.forbidden("Access token validation failed"); return Response.forbidden(
json.encode({"error": "Access token validation failed"}),
);
} }
final code = base64Url.encode( final code = base64Url.encode(
@ -41,9 +43,60 @@ class ApiHelper {
ref ref
.read(AuthCodeController.provider.notifier) .read(AuthCodeController.provider.notifier)
.set(code, MatrixUser(userId: userId, matrixToken: accessToken)); .set(
code,
MatrixUser(
userId: userId,
matrixToken: accessToken,
nonce: data["nonce"],
),
);
return Response.found("$redirectUri?code=$code&state=$state"); final uri = Uri.parse(redirectUri);
return Response.found(
uri.replace(
queryParameters: {
...uri.queryParameters,
"code": code,
"state": state,
"nonce": data["nonce"],
},
),
);
}
Future<Response> bridgeHandler(Request request) async {
final query = request.url.queryParameters;
final code = query["code"];
final redirectUri = query["redirect_uri"];
if (code == null || redirectUri == null) {
return Response(
400,
body: json.encode({"error": "Missing code or redirect_uri"}),
);
}
final tokenRes = await tokenHandler(
Request(
"POST",
Uri.base,
body: utf8.encode("code=$code&client_id=proxy"),
),
);
if (tokenRes.statusCode != 200) {
return Response(400, body: json.encode({"error": "Token post failed"}));
}
return Response.found(
redirectUri,
headers: {
"set-cookie":
"id_token=${json.decode(await tokenRes.readAsString())["id_token"]}; Path=/; Secure; HttpOnly; SameSite=Lax; Domain=.${ref.watch(SettingsController.provider)!.serviceDomain}; Max-Age=604800",
},
);
} }
Future<Response> tokenHandler(Request request) async { Future<Response> tokenHandler(Request request) async {
@ -53,26 +106,26 @@ class ApiHelper {
final clientId = body["client_id"]; final clientId = body["client_id"];
if (code == null || clientId == null) { if (code == null || clientId == null) {
return Response(400, body: "Missing code or client_id"); return Response(
400,
body: json.encode({"error": "Missing code or client_id"}),
);
} }
final codes = ref.read(AuthCodeController.provider); final codes = ref.read(AuthCodeController.provider);
if (!codes.containsKey(code)) { if (!codes.containsKey(code)) {
return Response(400, body: "Invalid code"); return Response(400, body: json.encode({"error": "Invalid code"}));
} }
final user = codes[code]!; final user = codes[code]!;
ref.read(AuthCodeController.provider.notifier).remove(code); ref.read(AuthCodeController.provider.notifier).remove(code);
final secret = await File.fromUri(
Uri.file(settings.jwtSecretFile),
).readAsString();
final jwt = JWT( final jwt = JWT(
{ {
"exp": "exp":
DateTime.now().add(Duration(days: 7)).millisecondsSinceEpoch ~/ DateTime.now().add(Duration(days: 7)).millisecondsSinceEpoch ~/
1000, 1000,
"nonce": user.nonce,
"iat": DateTime.now().millisecondsSinceEpoch ~/ 1000, "iat": DateTime.now().millisecondsSinceEpoch ~/ 1000,
}, },
subject: user.userId, subject: user.userId,
@ -80,13 +133,16 @@ class ApiHelper {
audience: Audience([clientId]), audience: Audience([clientId]),
); );
final token = jwt.sign(SecretKey(secret), algorithm: JWTAlgorithm.HS256); final token = jwt.sign(
await ref.read(KeyController.provider.future),
algorithm: JWTAlgorithm.HS256,
);
return Response.ok( return Response.ok(
json.encode({ json.encode({
"id_token": token, "id_token": token,
"access_token": token,
"token_type": "Bearer", "token_type": "Bearer",
"expires_in": 600,
}), }),
headers: {"Content-Type": "application/json"}, headers: {"Content-Type": "application/json"},
); );
@ -102,14 +158,33 @@ class ApiHelper {
final token = auth.substring(7); final token = auth.substring(7);
final jwt = JWT.verify( final jwt = JWT.verify(
token, token,
SecretKey( await ref.read(KeyController.provider.future),
await File.fromUri( );
Uri.file(ref.read(SettingsController.provider)!.jwtSecretFile),
).readAsString(), final settings = ref.read(SettingsController.provider)!;
final profile = await http.get(
Uri.parse(
"${settings.homeserver}/_matrix/client/v3/profile/${jwt.subject}",
), ),
); );
if (profile.statusCode != 200) {
return Response.forbidden(
json.encode({"error": "Access token validation failed"}),
);
}
final fullName = (json.decode(profile.body)["displayname"] as String);
final name = fullName.length <= 20 ? fullName : fullName.substring(0, 20);
return Response.ok( return Response.ok(
jsonEncode({"sub": jwt.subject}), jsonEncode({
"sub": jwt.subject,
"name": name,
"first_name": name,
"last_name": "",
"nickname": name,
}),
headers: {"Content-Type": "application/json"}, headers: {"Content-Type": "application/json"},
); );
} catch (e) { } catch (e) {
@ -117,10 +192,29 @@ class ApiHelper {
} }
} }
Response jwks(_) => Response.ok( Future<Response> introspectionHandler(Request request) async {
json.encode({"keys": []}), final token = Uri.splitQueryString(await request.readAsString())["token"];
if (token == null) {
return Response(400, body: json.encode({"error": "Missing token"}));
}
try {
JWT.verify(token, await ref.read(KeyController.provider.future));
return Response.ok(
json.encode({"active": true}),
headers: {"content-type": "application/json"}, headers: {"content-type": "application/json"},
); );
} catch (_) {
return Response.ok(
json.encode({"active": false}),
headers: {"content-type": "application/json"},
);
}
}
Future<Response> logoutHandler(Request request) async =>
Response.ok(json.encode("Log out is not currently implemented"));
Response openidConfiguration(_) { Response openidConfiguration(_) {
final settings = ref.read(SettingsController.provider)!; final settings = ref.read(SettingsController.provider)!;
@ -130,7 +224,8 @@ class ApiHelper {
"authorization_endpoint": settings.authorizeEndpoint, "authorization_endpoint": settings.authorizeEndpoint,
"token_endpoint": "${settings.issuer}/token", "token_endpoint": "${settings.issuer}/token",
"userinfo_endpoint": "${settings.issuer}/userinfo", "userinfo_endpoint": "${settings.issuer}/userinfo",
"jwks_uri": "${settings.issuer}/jwks.json", "introspection_endpoint": "${settings.issuer}/introspect",
"end_session_endpoint": "#",
"response_types_supported": ["code"], "response_types_supported": ["code"],
"subject_types_supported": ["public"], "subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["HS256"], "id_token_signing_alg_values_supported": ["HS256"],

View file

@ -8,6 +8,7 @@ abstract class MatrixUser with _$MatrixUser {
const factory MatrixUser({ const factory MatrixUser({
required String userId, required String userId,
required String matrixToken, required String matrixToken,
required String? nonce,
}) = _MatrixUser; }) = _MatrixUser;
factory MatrixUser.fromJson(Map<String, dynamic> json) => factory MatrixUser.fromJson(Map<String, dynamic> json) =>

View file

@ -4,7 +4,7 @@
// ignore_for_file: type=lint // ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of "matrix_user.dart"; part of 'matrix_user.dart';
// ************************************************************************** // **************************************************************************
// FreezedGenerator // FreezedGenerator
@ -16,11 +16,11 @@ T _$identity<T>(T value) => value;
/// @nodoc /// @nodoc
mixin _$MatrixUser { mixin _$MatrixUser {
String get userId; String get matrixToken; String get userId; String get matrixToken; String? get nonce;
/// Create a copy of MatrixUser /// Create a copy of MatrixUser
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@pragma("vm:prefer-inline") @pragma('vm:prefer-inline')
$MatrixUserCopyWith<MatrixUser> get copyWith => _$MatrixUserCopyWithImpl<MatrixUser>(this as MatrixUser, _$identity); $MatrixUserCopyWith<MatrixUser> get copyWith => _$MatrixUserCopyWithImpl<MatrixUser>(this as MatrixUser, _$identity);
/// Serializes this MatrixUser to a JSON map. /// Serializes this MatrixUser to a JSON map.
@ -29,16 +29,16 @@ $MatrixUserCopyWith<MatrixUser> get copyWith => _$MatrixUserCopyWithImpl<MatrixU
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is MatrixUser&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.matrixToken, matrixToken) || other.matrixToken == matrixToken)); return identical(this, other) || (other.runtimeType == runtimeType&&other is MatrixUser&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.matrixToken, matrixToken) || other.matrixToken == matrixToken)&&(identical(other.nonce, nonce) || other.nonce == nonce));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash(runtimeType,userId,matrixToken); int get hashCode => Object.hash(runtimeType,userId,matrixToken,nonce);
@override @override
String toString() { String toString() {
return "MatrixUser(userId: $userId, matrixToken: $matrixToken)"; return 'MatrixUser(userId: $userId, matrixToken: $matrixToken, nonce: $nonce)';
} }
@ -49,7 +49,7 @@ abstract mixin class $MatrixUserCopyWith<$Res> {
factory $MatrixUserCopyWith(MatrixUser value, $Res Function(MatrixUser) _then) = _$MatrixUserCopyWithImpl; factory $MatrixUserCopyWith(MatrixUser value, $Res Function(MatrixUser) _then) = _$MatrixUserCopyWithImpl;
@useResult @useResult
$Res call({ $Res call({
String userId, String matrixToken String userId, String matrixToken, String? nonce
}); });
@ -66,11 +66,12 @@ class _$MatrixUserCopyWithImpl<$Res>
/// Create a copy of MatrixUser /// Create a copy of MatrixUser
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@pragma("vm:prefer-inline") @override $Res call({Object? userId = null,Object? matrixToken = null,}) { @pragma('vm:prefer-inline') @override $Res call({Object? userId = null,Object? matrixToken = null,Object? nonce = freezed,}) {
return _then(_self.copyWith( return _then(_self.copyWith(
userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
as String,matrixToken: null == matrixToken ? _self.matrixToken : matrixToken // ignore: cast_nullable_to_non_nullable as String,matrixToken: null == matrixToken ? _self.matrixToken : matrixToken // ignore: cast_nullable_to_non_nullable
as String, as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
as String?,
)); ));
} }
@ -81,16 +82,17 @@ as String,
@JsonSerializable() @JsonSerializable()
class _MatrixUser implements MatrixUser { class _MatrixUser implements MatrixUser {
const _MatrixUser({required this.userId, required this.matrixToken}); const _MatrixUser({required this.userId, required this.matrixToken, required this.nonce});
factory _MatrixUser.fromJson(Map<String, dynamic> json) => _$MatrixUserFromJson(json); factory _MatrixUser.fromJson(Map<String, dynamic> json) => _$MatrixUserFromJson(json);
@override final String userId; @override final String userId;
@override final String matrixToken; @override final String matrixToken;
@override final String? nonce;
/// Create a copy of MatrixUser /// Create a copy of MatrixUser
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false) @override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma("vm:prefer-inline") @pragma('vm:prefer-inline')
_$MatrixUserCopyWith<_MatrixUser> get copyWith => __$MatrixUserCopyWithImpl<_MatrixUser>(this, _$identity); _$MatrixUserCopyWith<_MatrixUser> get copyWith => __$MatrixUserCopyWithImpl<_MatrixUser>(this, _$identity);
@override @override
@ -100,16 +102,16 @@ Map<String, dynamic> toJson() {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _MatrixUser&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.matrixToken, matrixToken) || other.matrixToken == matrixToken)); return identical(this, other) || (other.runtimeType == runtimeType&&other is _MatrixUser&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.matrixToken, matrixToken) || other.matrixToken == matrixToken)&&(identical(other.nonce, nonce) || other.nonce == nonce));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash(runtimeType,userId,matrixToken); int get hashCode => Object.hash(runtimeType,userId,matrixToken,nonce);
@override @override
String toString() { String toString() {
return "MatrixUser(userId: $userId, matrixToken: $matrixToken)"; return 'MatrixUser(userId: $userId, matrixToken: $matrixToken, nonce: $nonce)';
} }
@ -120,7 +122,7 @@ abstract mixin class _$MatrixUserCopyWith<$Res> implements $MatrixUserCopyWith<$
factory _$MatrixUserCopyWith(_MatrixUser value, $Res Function(_MatrixUser) _then) = __$MatrixUserCopyWithImpl; factory _$MatrixUserCopyWith(_MatrixUser value, $Res Function(_MatrixUser) _then) = __$MatrixUserCopyWithImpl;
@override @useResult @override @useResult
$Res call({ $Res call({
String userId, String matrixToken String userId, String matrixToken, String? nonce
}); });
@ -137,11 +139,12 @@ class __$MatrixUserCopyWithImpl<$Res>
/// Create a copy of MatrixUser /// Create a copy of MatrixUser
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @pragma("vm:prefer-inline") $Res call({Object? userId = null,Object? matrixToken = null,}) { @override @pragma('vm:prefer-inline') $Res call({Object? userId = null,Object? matrixToken = null,Object? nonce = freezed,}) {
return _then(_MatrixUser( return _then(_MatrixUser(
userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
as String,matrixToken: null == matrixToken ? _self.matrixToken : matrixToken // ignore: cast_nullable_to_non_nullable as String,matrixToken: null == matrixToken ? _self.matrixToken : matrixToken // ignore: cast_nullable_to_non_nullable
as String, as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
as String?,
)); ));
} }

View file

@ -1,18 +1,20 @@
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
part of "matrix_user.dart"; part of 'matrix_user.dart';
// ************************************************************************** // **************************************************************************
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
_MatrixUser _$MatrixUserFromJson(Map<String, dynamic> json) => _MatrixUser( _MatrixUser _$MatrixUserFromJson(Map<String, dynamic> json) => _MatrixUser(
userId: json["userId"] as String, userId: json['userId'] as String,
matrixToken: json["matrixToken"] as String, matrixToken: json['matrixToken'] as String,
nonce: json['nonce'] as String?,
); );
Map<String, dynamic> _$MatrixUserToJson(_MatrixUser instance) => Map<String, dynamic> _$MatrixUserToJson(_MatrixUser instance) =>
<String, dynamic>{ <String, dynamic>{
"userId": instance.userId, 'userId': instance.userId,
"matrixToken": instance.matrixToken, 'matrixToken': instance.matrixToken,
'nonce': instance.nonce,
}; };

View file

@ -7,11 +7,11 @@ part "settings.g.dart";
abstract class Settings with _$Settings { abstract class Settings with _$Settings {
const factory Settings({ const factory Settings({
required String? socket, required String? socket,
required String serviceDomain,
required String address, required String address,
required String port, required String port,
required String homeserver, required String homeserver,
required String issuer, required String issuer,
required String serviceDomain,
required String jwtSecretFile, required String jwtSecretFile,
required String authorizeEndpoint, required String authorizeEndpoint,
}) = _Settings; }) = _Settings;

View file

@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
/// @nodoc /// @nodoc
mixin _$Settings { mixin _$Settings {
String? get socket; String get address; String get port; String get homeserver; String get issuer; String get serviceDomain; String get jwtSecretFile; String get authorizeEndpoint; String? get socket; String get serviceDomain; String get address; String get port; String get homeserver; String get issuer; String get jwtSecretFile; String get authorizeEndpoint;
/// Create a copy of Settings /// Create a copy of Settings
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@ -29,16 +29,16 @@ $SettingsCopyWith<Settings> get copyWith => _$SettingsCopyWithImpl<Settings>(thi
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.address, address) || other.address == address)&&(identical(other.port, port) || other.port == port)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.issuer, issuer) || other.issuer == issuer)&&(identical(other.serviceDomain, serviceDomain) || other.serviceDomain == serviceDomain)&&(identical(other.jwtSecretFile, jwtSecretFile) || other.jwtSecretFile == jwtSecretFile)&&(identical(other.authorizeEndpoint, authorizeEndpoint) || other.authorizeEndpoint == authorizeEndpoint)); return identical(this, other) || (other.runtimeType == runtimeType&&other is Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.serviceDomain, serviceDomain) || other.serviceDomain == serviceDomain)&&(identical(other.address, address) || other.address == address)&&(identical(other.port, port) || other.port == port)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.issuer, issuer) || other.issuer == issuer)&&(identical(other.jwtSecretFile, jwtSecretFile) || other.jwtSecretFile == jwtSecretFile)&&(identical(other.authorizeEndpoint, authorizeEndpoint) || other.authorizeEndpoint == authorizeEndpoint));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash(runtimeType,socket,address,port,homeserver,issuer,serviceDomain,jwtSecretFile,authorizeEndpoint); int get hashCode => Object.hash(runtimeType,socket,serviceDomain,address,port,homeserver,issuer,jwtSecretFile,authorizeEndpoint);
@override @override
String toString() { String toString() {
return "Settings(socket: $socket, address: $address, port: $port, homeserver: $homeserver, issuer: $issuer, serviceDomain: $serviceDomain, jwtSecretFile: $jwtSecretFile, authorizeEndpoint: $authorizeEndpoint)"; return "Settings(socket: $socket, serviceDomain: $serviceDomain, address: $address, port: $port, homeserver: $homeserver, issuer: $issuer, jwtSecretFile: $jwtSecretFile, authorizeEndpoint: $authorizeEndpoint)";
} }
@ -49,7 +49,7 @@ abstract mixin class $SettingsCopyWith<$Res> {
factory $SettingsCopyWith(Settings value, $Res Function(Settings) _then) = _$SettingsCopyWithImpl; factory $SettingsCopyWith(Settings value, $Res Function(Settings) _then) = _$SettingsCopyWithImpl;
@useResult @useResult
$Res call({ $Res call({
String? socket, String address, String port, String homeserver, String issuer, String serviceDomain, String jwtSecretFile, String authorizeEndpoint String? socket, String serviceDomain, String address, String port, String homeserver, String issuer, String jwtSecretFile, String authorizeEndpoint
}); });
@ -66,14 +66,14 @@ class _$SettingsCopyWithImpl<$Res>
/// Create a copy of Settings /// Create a copy of Settings
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@pragma("vm:prefer-inline") @override $Res call({Object? socket = freezed,Object? address = null,Object? port = null,Object? homeserver = null,Object? issuer = null,Object? serviceDomain = null,Object? jwtSecretFile = null,Object? authorizeEndpoint = null,}) { @pragma("vm:prefer-inline") @override $Res call({Object? socket = freezed,Object? serviceDomain = null,Object? address = null,Object? port = null,Object? homeserver = null,Object? issuer = null,Object? jwtSecretFile = null,Object? authorizeEndpoint = null,}) {
return _then(_self.copyWith( return _then(_self.copyWith(
socket: freezed == socket ? _self.socket : socket // ignore: cast_nullable_to_non_nullable socket: freezed == socket ? _self.socket : socket // ignore: cast_nullable_to_non_nullable
as String?,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable as String?,serviceDomain: null == serviceDomain ? _self.serviceDomain : serviceDomain // ignore: cast_nullable_to_non_nullable
as String,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable
as String,port: null == port ? _self.port : port // ignore: cast_nullable_to_non_nullable as String,port: null == port ? _self.port : port // ignore: cast_nullable_to_non_nullable
as String,homeserver: null == homeserver ? _self.homeserver : homeserver // ignore: cast_nullable_to_non_nullable as String,homeserver: null == homeserver ? _self.homeserver : homeserver // ignore: cast_nullable_to_non_nullable
as String,issuer: null == issuer ? _self.issuer : issuer // ignore: cast_nullable_to_non_nullable as String,issuer: null == issuer ? _self.issuer : issuer // ignore: cast_nullable_to_non_nullable
as String,serviceDomain: null == serviceDomain ? _self.serviceDomain : serviceDomain // ignore: cast_nullable_to_non_nullable
as String,jwtSecretFile: null == jwtSecretFile ? _self.jwtSecretFile : jwtSecretFile // ignore: cast_nullable_to_non_nullable as String,jwtSecretFile: null == jwtSecretFile ? _self.jwtSecretFile : jwtSecretFile // ignore: cast_nullable_to_non_nullable
as String,authorizeEndpoint: null == authorizeEndpoint ? _self.authorizeEndpoint : authorizeEndpoint // ignore: cast_nullable_to_non_nullable as String,authorizeEndpoint: null == authorizeEndpoint ? _self.authorizeEndpoint : authorizeEndpoint // ignore: cast_nullable_to_non_nullable
as String, as String,
@ -87,15 +87,15 @@ as String,
@JsonSerializable() @JsonSerializable()
class _Settings implements Settings { class _Settings implements Settings {
const _Settings({required this.socket, required this.address, required this.port, required this.homeserver, required this.issuer, required this.serviceDomain, required this.jwtSecretFile, required this.authorizeEndpoint}); const _Settings({required this.socket, required this.serviceDomain, required this.address, required this.port, required this.homeserver, required this.issuer, required this.jwtSecretFile, required this.authorizeEndpoint});
factory _Settings.fromJson(Map<String, dynamic> json) => _$SettingsFromJson(json); factory _Settings.fromJson(Map<String, dynamic> json) => _$SettingsFromJson(json);
@override final String? socket; @override final String? socket;
@override final String serviceDomain;
@override final String address; @override final String address;
@override final String port; @override final String port;
@override final String homeserver; @override final String homeserver;
@override final String issuer; @override final String issuer;
@override final String serviceDomain;
@override final String jwtSecretFile; @override final String jwtSecretFile;
@override final String authorizeEndpoint; @override final String authorizeEndpoint;
@ -112,16 +112,16 @@ Map<String, dynamic> toJson() {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.address, address) || other.address == address)&&(identical(other.port, port) || other.port == port)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.issuer, issuer) || other.issuer == issuer)&&(identical(other.serviceDomain, serviceDomain) || other.serviceDomain == serviceDomain)&&(identical(other.jwtSecretFile, jwtSecretFile) || other.jwtSecretFile == jwtSecretFile)&&(identical(other.authorizeEndpoint, authorizeEndpoint) || other.authorizeEndpoint == authorizeEndpoint)); return identical(this, other) || (other.runtimeType == runtimeType&&other is _Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.serviceDomain, serviceDomain) || other.serviceDomain == serviceDomain)&&(identical(other.address, address) || other.address == address)&&(identical(other.port, port) || other.port == port)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.issuer, issuer) || other.issuer == issuer)&&(identical(other.jwtSecretFile, jwtSecretFile) || other.jwtSecretFile == jwtSecretFile)&&(identical(other.authorizeEndpoint, authorizeEndpoint) || other.authorizeEndpoint == authorizeEndpoint));
} }
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@override @override
int get hashCode => Object.hash(runtimeType,socket,address,port,homeserver,issuer,serviceDomain,jwtSecretFile,authorizeEndpoint); int get hashCode => Object.hash(runtimeType,socket,serviceDomain,address,port,homeserver,issuer,jwtSecretFile,authorizeEndpoint);
@override @override
String toString() { String toString() {
return "Settings(socket: $socket, address: $address, port: $port, homeserver: $homeserver, issuer: $issuer, serviceDomain: $serviceDomain, jwtSecretFile: $jwtSecretFile, authorizeEndpoint: $authorizeEndpoint)"; return "Settings(socket: $socket, serviceDomain: $serviceDomain, address: $address, port: $port, homeserver: $homeserver, issuer: $issuer, jwtSecretFile: $jwtSecretFile, authorizeEndpoint: $authorizeEndpoint)";
} }
@ -132,7 +132,7 @@ abstract mixin class _$SettingsCopyWith<$Res> implements $SettingsCopyWith<$Res>
factory _$SettingsCopyWith(_Settings value, $Res Function(_Settings) _then) = __$SettingsCopyWithImpl; factory _$SettingsCopyWith(_Settings value, $Res Function(_Settings) _then) = __$SettingsCopyWithImpl;
@override @useResult @override @useResult
$Res call({ $Res call({
String? socket, String address, String port, String homeserver, String issuer, String serviceDomain, String jwtSecretFile, String authorizeEndpoint String? socket, String serviceDomain, String address, String port, String homeserver, String issuer, String jwtSecretFile, String authorizeEndpoint
}); });
@ -149,14 +149,14 @@ class __$SettingsCopyWithImpl<$Res>
/// Create a copy of Settings /// Create a copy of Settings
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @pragma("vm:prefer-inline") $Res call({Object? socket = freezed,Object? address = null,Object? port = null,Object? homeserver = null,Object? issuer = null,Object? serviceDomain = null,Object? jwtSecretFile = null,Object? authorizeEndpoint = null,}) { @override @pragma("vm:prefer-inline") $Res call({Object? socket = freezed,Object? serviceDomain = null,Object? address = null,Object? port = null,Object? homeserver = null,Object? issuer = null,Object? jwtSecretFile = null,Object? authorizeEndpoint = null,}) {
return _then(_Settings( return _then(_Settings(
socket: freezed == socket ? _self.socket : socket // ignore: cast_nullable_to_non_nullable socket: freezed == socket ? _self.socket : socket // ignore: cast_nullable_to_non_nullable
as String?,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable as String?,serviceDomain: null == serviceDomain ? _self.serviceDomain : serviceDomain // ignore: cast_nullable_to_non_nullable
as String,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable
as String,port: null == port ? _self.port : port // ignore: cast_nullable_to_non_nullable as String,port: null == port ? _self.port : port // ignore: cast_nullable_to_non_nullable
as String,homeserver: null == homeserver ? _self.homeserver : homeserver // ignore: cast_nullable_to_non_nullable as String,homeserver: null == homeserver ? _self.homeserver : homeserver // ignore: cast_nullable_to_non_nullable
as String,issuer: null == issuer ? _self.issuer : issuer // ignore: cast_nullable_to_non_nullable as String,issuer: null == issuer ? _self.issuer : issuer // ignore: cast_nullable_to_non_nullable
as String,serviceDomain: null == serviceDomain ? _self.serviceDomain : serviceDomain // ignore: cast_nullable_to_non_nullable
as String,jwtSecretFile: null == jwtSecretFile ? _self.jwtSecretFile : jwtSecretFile // ignore: cast_nullable_to_non_nullable as String,jwtSecretFile: null == jwtSecretFile ? _self.jwtSecretFile : jwtSecretFile // ignore: cast_nullable_to_non_nullable
as String,authorizeEndpoint: null == authorizeEndpoint ? _self.authorizeEndpoint : authorizeEndpoint // ignore: cast_nullable_to_non_nullable as String,authorizeEndpoint: null == authorizeEndpoint ? _self.authorizeEndpoint : authorizeEndpoint // ignore: cast_nullable_to_non_nullable
as String, as String,

View file

@ -8,22 +8,22 @@ part of "settings.dart";
_Settings _$SettingsFromJson(Map<String, dynamic> json) => _Settings( _Settings _$SettingsFromJson(Map<String, dynamic> json) => _Settings(
socket: json["socket"] as String?, socket: json["socket"] as String?,
serviceDomain: json["serviceDomain"] as String,
address: json["address"] as String, address: json["address"] as String,
port: json["port"] as String, port: json["port"] as String,
homeserver: json["homeserver"] as String, homeserver: json["homeserver"] as String,
issuer: json["issuer"] as String, issuer: json["issuer"] as String,
serviceDomain: json["serviceDomain"] as String,
jwtSecretFile: json["jwtSecretFile"] as String, jwtSecretFile: json["jwtSecretFile"] as String,
authorizeEndpoint: json["authorizeEndpoint"] as String, authorizeEndpoint: json["authorizeEndpoint"] as String,
); );
Map<String, dynamic> _$SettingsToJson(_Settings instance) => <String, dynamic>{ Map<String, dynamic> _$SettingsToJson(_Settings instance) => <String, dynamic>{
"socket": instance.socket, "socket": instance.socket,
"serviceDomain": instance.serviceDomain,
"address": instance.address, "address": instance.address,
"port": instance.port, "port": instance.port,
"homeserver": instance.homeserver, "homeserver": instance.homeserver,
"issuer": instance.issuer, "issuer": instance.issuer,
"serviceDomain": instance.serviceDomain,
"jwtSecretFile": instance.jwtSecretFile, "jwtSecretFile": instance.jwtSecretFile,
"authorizeEndpoint": instance.authorizeEndpoint, "authorizeEndpoint": instance.authorizeEndpoint,
}; };

80
module.nix Normal file
View file

@ -0,0 +1,80 @@
self: {
config,
lib,
pkgs,
utils,
...
}: let
cfg = config.services.matrixoidc;
in {
meta.maintainers = with lib.maintainers; [quadradical];
options.services.matrixoidc = {
enable = lib.mkEnableOption "the matrixoidc server";
package = lib.mkPackageOption self.packages.${pkgs.system} "default" {};
jwtSecretFile = lib.mkOption {
type = lib.types.path;
};
group = lib.mkOption {
type = lib.types.str;
default = "matrixoidc";
};
args = lib.mkOption {
type = with lib.types; listOf str;
default = [];
};
};
config = lib.mkIf cfg.enable {
systemd.services.matrixoidc = {
description = "matrixoidc server";
documentation = ["https://git.federated.nexus/Henry-Hiles/matrixoidc"];
wantedBy = ["multi-user.target"];
wants = ["network-online.target"];
after = ["network-online.target"];
serviceConfig = {
LoadCredential = ["matrixoidc-secrets:${cfg.jwtSecretFile}"];
ExecStart = utils.escapeSystemdExecArgs ([
(lib.getExe cfg.package)
"--jwtSecretFile=/run/credentials/matrixoidc.service/matrixoidc-secrets"
]
++ cfg.args);
DynamicUser = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
PrivateDevices = true;
PrivateMounts = true;
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
];
RestrictNamespaces = true;
RestrictRealtime = true;
ProtectHome = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
"~@resources"
];
Restart = "aslways";
RestartSec = 5;
UMask = 007;
RuntimeDirectory = "matrixoidc";
RuntimeDirectoryMode = 0770;
Group = cfg.group;
};
};
};
}

View file

@ -121,6 +121,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.4" version: "2.0.4"
ci:
dependency: transitive
description:
name: ci
sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13"
url: "https://pub.dev"
source: hosted
version: "0.1.0"
cli_tools:
dependency: "direct main"
description:
name: cli_tools
sha256: ed6d1cef6e34ff3d68e7c798c3d18f497a311ac8082533340a4a914b12344717
url: "https://pub.dev"
source: hosted
version: "0.6.0"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -169,6 +185,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.0" version: "3.2.0"
dart_mappable:
dependency: transitive
description:
name: dart_mappable
sha256: "2255b2c00e328a65fef5a8df2dabfc0dc9c2e518c33a50051a4519b1c7a28c48"
url: "https://pub.dev"
source: hosted
version: "4.5.0"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
@ -353,6 +377,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
oauth2:
dependency: transitive
description:
name: oauth2
sha256: c84470642cbb2bec450ccab2f8520c079cd1ca546a76ffd5c40589e07f4e8bf4
url: "https://pub.dev"
source: hosted
version: "2.0.3"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
@ -385,6 +417,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.1" version: "1.5.1"
pub_api_client:
dependency: transitive
description:
name: pub_api_client
sha256: b9c0184ce4a562d8cf2ebd7be235a25aa158b7c01bdef863cccadc5894644e26
url: "https://pub.dev"
source: hosted
version: "3.1.1"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
@ -401,6 +441,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.0" version: "1.5.0"
rfc_6901:
dependency: transitive
description:
name: rfc_6901
sha256: df1bbfa3d023009598f19636d6114c6ac1e0b7bb7bf6a260f0e6e6ce91416820
url: "https://pub.dev"
source: hosted
version: "0.2.0"
riverpod: riverpod:
dependency: "direct main" dependency: "direct main"
description: description:
@ -497,6 +545,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.1" version: "1.4.1"
super_string:
dependency: transitive
description:
name: super_string
sha256: ba41acf9fbb318b3fc0d57c9235779100394d85d83f45ab533615df1f3146ea7
url: "https://pub.dev"
source: hosted
version: "1.0.3"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
@ -521,6 +577,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "1.0.2"
type_plus:
dependency: transitive
description:
name: type_plus
sha256: d5d1019471f0d38b91603adb9b5fd4ce7ab903c879d2fbf1a3f80a630a03fcc9
url: "https://pub.dev"
source: hosted
version: "2.1.1"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:

797
pubspec.lock.json Normal file
View file

@ -0,0 +1,797 @@
{
"packages": {
"_fe_analyzer_shared": {
"dependency": "transitive",
"description": {
"name": "_fe_analyzer_shared",
"sha256": "e55636ed79578b9abca5fecf9437947798f5ef7456308b5cb85720b793eac92f",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "82.0.0"
},
"adaptive_number": {
"dependency": "transitive",
"description": {
"name": "adaptive_number",
"sha256": "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.0.0"
},
"analyzer": {
"dependency": "transitive",
"description": {
"name": "analyzer",
"sha256": "904ae5bb474d32c38fb9482e2d925d5454cda04ddd0e55d2e6826bc72f6ba8c0",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "7.4.5"
},
"args": {
"dependency": "transitive",
"description": {
"name": "args",
"sha256": "d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.7.0"
},
"async": {
"dependency": "transitive",
"description": {
"name": "async",
"sha256": "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.13.0"
},
"boolean_selector": {
"dependency": "transitive",
"description": {
"name": "boolean_selector",
"sha256": "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.1.2"
},
"build": {
"dependency": "transitive",
"description": {
"name": "build",
"sha256": "486337d40a48d75049f2a01efceefc1412e3a6d6342d39624753e7d5a4e70016",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.5.1"
},
"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": "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "4.0.4"
},
"build_resolvers": {
"dependency": "transitive",
"description": {
"name": "build_resolvers",
"sha256": "abe6e4b5b36ce2bf01aec8f2a59424d1ecfc3cb340e7145a64359adc7233a0d1",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.5.1"
},
"build_runner": {
"dependency": "direct dev",
"description": {
"name": "build_runner",
"sha256": "398ec7898b9b60be126067835a8202240b26dc54aa34d91d0198a539dcd5942e",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.5.1"
},
"build_runner_core": {
"dependency": "transitive",
"description": {
"name": "build_runner_core",
"sha256": "9821dbf604ed74a6dabeaba0c33ac58190332ea238862a62cdf25fc8eba226b8",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "9.0.1"
},
"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": "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "8.10.1"
},
"checked_yaml": {
"dependency": "transitive",
"description": {
"name": "checked_yaml",
"sha256": "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.0.4"
},
"ci": {
"dependency": "transitive",
"description": {
"name": "ci",
"sha256": "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "0.1.0"
},
"cli_tools": {
"dependency": "direct main",
"description": {
"name": "cli_tools",
"sha256": "ed6d1cef6e34ff3d68e7c798c3d18f497a311ac8082533340a4a914b12344717",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "0.6.0"
},
"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": {
"name": "collection",
"sha256": "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.19.1"
},
"convert": {
"dependency": "transitive",
"description": {
"name": "convert",
"sha256": "b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.1.2"
},
"crypto": {
"dependency": "transitive",
"description": {
"name": "crypto",
"sha256": "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.0.6"
},
"dart_jsonwebtoken": {
"dependency": "direct main",
"description": {
"name": "dart_jsonwebtoken",
"sha256": "21ce9f8a8712f741e8d6876a9c82c0f8a257fe928c4378a91d8527b92a3fd413",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.2.0"
},
"dart_mappable": {
"dependency": "transitive",
"description": {
"name": "dart_mappable",
"sha256": "2255b2c00e328a65fef5a8df2dabfc0dc9c2e518c33a50051a4519b1c7a28c48",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "4.5.0"
},
"dart_style": {
"dependency": "transitive",
"description": {
"name": "dart_style",
"sha256": "5b236382b47ee411741447c1f1e111459c941ea1b3f2b540dde54c210a3662af",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.1.0"
},
"ed25519_edwards": {
"dependency": "transitive",
"description": {
"name": "ed25519_edwards",
"sha256": "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "0.3.1"
},
"fast_immutable_collections": {
"dependency": "direct main",
"description": {
"name": "fast_immutable_collections",
"sha256": "d1aa3d7788fab06cce7f303f4969c7a16a10c865e1bd2478291a8ebcbee084e5",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "11.0.4"
},
"file": {
"dependency": "transitive",
"description": {
"name": "file",
"sha256": "a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4",
"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"
},
"freezed": {
"dependency": "direct dev",
"description": {
"name": "freezed",
"sha256": "6022db4c7bfa626841b2a10f34dd1e1b68e8f8f9650db6112dcdeeca45ca793c",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.0.6"
},
"freezed_annotation": {
"dependency": "direct main",
"description": {
"name": "freezed_annotation",
"sha256": "c87ff004c8aa6af2d531668b46a4ea379f7191dc6dfa066acd53d506da6e044b",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.0.0"
},
"frontend_server_client": {
"dependency": "transitive",
"description": {
"name": "frontend_server_client",
"sha256": "f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "4.0.0"
},
"glob": {
"dependency": "transitive",
"description": {
"name": "glob",
"sha256": "c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de",
"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": {
"dependency": "direct main",
"description": {
"name": "http",
"sha256": "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.4.0"
},
"http_methods": {
"dependency": "transitive",
"description": {
"name": "http_methods",
"sha256": "6bccce8f1ec7b5d701e7921dca35e202d425b57e317ba1a37f2638590e29e566",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.1.1"
},
"http_multi_server": {
"dependency": "transitive",
"description": {
"name": "http_multi_server",
"sha256": "aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.2.2"
},
"http_parser": {
"dependency": "transitive",
"description": {
"name": "http_parser",
"sha256": "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "4.1.2"
},
"io": {
"dependency": "transitive",
"description": {
"name": "io",
"sha256": "dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.0.5"
},
"js": {
"dependency": "transitive",
"description": {
"name": "js",
"sha256": "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "0.7.2"
},
"json_annotation": {
"dependency": "direct main",
"description": {
"name": "json_annotation",
"sha256": "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "4.9.0"
},
"json_serializable": {
"dependency": "direct dev",
"description": {
"name": "json_serializable",
"sha256": "c50ef5fc083d5b5e12eef489503ba3bf5ccc899e487d691584699b4bdefeea8c",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "6.9.5"
},
"lints": {
"dependency": "direct dev",
"description": {
"name": "lints",
"sha256": "a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "6.0.0"
},
"logging": {
"dependency": "transitive",
"description": {
"name": "logging",
"sha256": "c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.3.0"
},
"matcher": {
"dependency": "transitive",
"description": {
"name": "matcher",
"sha256": "dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "0.12.17"
},
"meta": {
"dependency": "transitive",
"description": {
"name": "meta",
"sha256": "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.17.0"
},
"mime": {
"dependency": "transitive",
"description": {
"name": "mime",
"sha256": "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.0.0"
},
"oauth2": {
"dependency": "transitive",
"description": {
"name": "oauth2",
"sha256": "c84470642cbb2bec450ccab2f8520c079cd1ca546a76ffd5c40589e07f4e8bf4",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.0.3"
},
"package_config": {
"dependency": "transitive",
"description": {
"name": "package_config",
"sha256": "f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.2.0"
},
"path": {
"dependency": "transitive",
"description": {
"name": "path",
"sha256": "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.9.1"
},
"pointycastle": {
"dependency": "transitive",
"description": {
"name": "pointycastle",
"sha256": "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "4.0.0"
},
"pool": {
"dependency": "transitive",
"description": {
"name": "pool",
"sha256": "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.5.1"
},
"pub_api_client": {
"dependency": "transitive",
"description": {
"name": "pub_api_client",
"sha256": "b9c0184ce4a562d8cf2ebd7be235a25aa158b7c01bdef863cccadc5894644e26",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.1.1"
},
"pub_semver": {
"dependency": "transitive",
"description": {
"name": "pub_semver",
"sha256": "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.2.0"
},
"pubspec_parse": {
"dependency": "transitive",
"description": {
"name": "pubspec_parse",
"sha256": "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.5.0"
},
"rfc_6901": {
"dependency": "transitive",
"description": {
"name": "rfc_6901",
"sha256": "df1bbfa3d023009598f19636d6114c6ac1e0b7bb7bf6a260f0e6e6ce91416820",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "0.2.0"
},
"riverpod": {
"dependency": "direct main",
"description": {
"name": "riverpod",
"sha256": "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.6.1"
},
"shelf": {
"dependency": "direct main",
"description": {
"name": "shelf",
"sha256": "e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.4.2"
},
"shelf_router": {
"dependency": "direct main",
"description": {
"name": "shelf_router",
"sha256": "f5e5d492440a7fb165fe1e2e1a623f31f734d3370900070b2b1e0d0428d59864",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.1.4"
},
"shelf_web_socket": {
"dependency": "transitive",
"description": {
"name": "shelf_web_socket",
"sha256": "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.0.0"
},
"source_gen": {
"dependency": "transitive",
"description": {
"name": "source_gen",
"sha256": "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.0.0"
},
"source_helper": {
"dependency": "transitive",
"description": {
"name": "source_helper",
"sha256": "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.3.5"
},
"source_span": {
"dependency": "transitive",
"description": {
"name": "source_span",
"sha256": "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.10.1"
},
"stack_trace": {
"dependency": "transitive",
"description": {
"name": "stack_trace",
"sha256": "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.12.1"
},
"state_notifier": {
"dependency": "transitive",
"description": {
"name": "state_notifier",
"sha256": "b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.0.0"
},
"stream_channel": {
"dependency": "transitive",
"description": {
"name": "stream_channel",
"sha256": "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d",
"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": {
"name": "string_scanner",
"sha256": "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.4.1"
},
"super_string": {
"dependency": "transitive",
"description": {
"name": "super_string",
"sha256": "ba41acf9fbb318b3fc0d57c9235779100394d85d83f45ab533615df1f3146ea7",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.0.3"
},
"term_glyph": {
"dependency": "transitive",
"description": {
"name": "term_glyph",
"sha256": "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.2.2"
},
"test_api": {
"dependency": "transitive",
"description": {
"name": "test_api",
"sha256": "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "0.7.6"
},
"timing": {
"dependency": "transitive",
"description": {
"name": "timing",
"sha256": "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.0.2"
},
"type_plus": {
"dependency": "transitive",
"description": {
"name": "type_plus",
"sha256": "d5d1019471f0d38b91603adb9b5fd4ce7ab903c879d2fbf1a3f80a630a03fcc9",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "2.1.1"
},
"typed_data": {
"dependency": "transitive",
"description": {
"name": "typed_data",
"sha256": "f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.4.0"
},
"watcher": {
"dependency": "transitive",
"description": {
"name": "watcher",
"sha256": "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.1.2"
},
"web": {
"dependency": "transitive",
"description": {
"name": "web",
"sha256": "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.1.1"
},
"web_socket": {
"dependency": "transitive",
"description": {
"name": "web_socket",
"sha256": "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "1.0.1"
},
"web_socket_channel": {
"dependency": "transitive",
"description": {
"name": "web_socket_channel",
"sha256": "d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.0.3"
},
"yaml": {
"dependency": "transitive",
"description": {
"name": "yaml",
"sha256": "b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce",
"url": "https://pub.dev"
},
"source": "hosted",
"version": "3.1.3"
}
},
"sdks": {
"dart": ">=3.8.0 <4.0.0"
}
}

View file

@ -2,6 +2,8 @@ name: matrixoidc
description: A minimal OpenID Connect provider backed by Matrix. description: A minimal OpenID Connect provider backed by Matrix.
version: 1.0.0 version: 1.0.0
publish_to: none publish_to: none
executables:
matrixoidc:
environment: environment:
sdk: ^3.8.0 sdk: ^3.8.0
@ -14,8 +16,9 @@ dependencies:
freezed_annotation: ^3.0.0 freezed_annotation: ^3.0.0
json_annotation: ^4.9.0 json_annotation: ^4.9.0
shelf_router: ^1.1.4 shelf_router: ^1.1.4
args: ^2.7.0
fast_immutable_collections: ^11.0.4 fast_immutable_collections: ^11.0.4
cli_tools: ^0.6.0
args: ^2.7.0
dev_dependencies: dev_dependencies:
build_runner: ^2.4.6 build_runner: ^2.4.6