Skip to content

Commit

Permalink
Implement session support
Browse files Browse the repository at this point in the history
  • Loading branch information
l7ssha committed Nov 18, 2024
1 parent caa5b37 commit 843e30e
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 70 deletions.
2 changes: 1 addition & 1 deletion lib/running_on_dart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ export 'src/converter.dart';
export 'src/error_handler.dart';
export 'src/init.dart';

export 'src/api/api_server.dart' show WebServer;
export 'src/web_app/api_server.dart' show WebServer;
68 changes: 0 additions & 68 deletions lib/src/api/api_server.dart

This file was deleted.

100 changes: 100 additions & 0 deletions lib/src/web_app/api_server.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import 'dart:convert';

import 'package:injector/injector.dart';

import 'package:running_on_dart/running_on_dart.dart';
import 'package:running_on_dart/src/web_app/utils.dart';
import 'package:running_on_dart/src/services/bot_info.dart';
import 'package:shelf_cors_headers/shelf_cors_headers.dart';

import 'package:shelf_router/shelf_router.dart' as shelf_router;
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf_io;

import 'package:http/http.dart' as http;
import 'package:shelf_session/cookies_middleware.dart';
import 'package:shelf_session/session_middleware.dart';

final clientId = getEnv('DISCORD_CLIENT_ID');
final clientSecret = getEnv('DISCORD_CLIENT_SECRET');
final clientRedirectUri = getEnv('DISCORD_REDIRECT_URI');

class WebServer {
Future<shelf.Response> _handleIndex(shelf.Request request) async {
final data = await Injector.appInstance.get<BotInfoService>().getCurrentBotInfo();

return createTwigResponse("index.html", parameters: {
...data.toJson(),
'clientId': clientId,
'redirectUri': clientRedirectUri,
'user_data': Session.getSession(request)?.data['user_data'] ?? false,
});
}

Future<shelf.Response> _handleRedirect(shelf.Request request) async {
final authCode = request.url.queryParameters['code'];

final tokenResponse = await http.post(Uri.https('discord.com', '/api/oauth2/token'), body: {
'client_id': clientId,
'client_secret': clientSecret,
'redirect_uri': clientRedirectUri,
'grant_type': 'authorization_code',
'code': authCode,
}, headers: {
'Content-Type': 'application/x-www-form-urlencoded',
});

final tokenBodyJson = jsonDecode(tokenResponse.body);
final token = tokenBodyJson['access_token'];

print(tokenResponse.body);
print(tokenResponse.statusCode);

final userData = await http.get(Uri.https('discord.com', '/api/oauth2/@me'), headers: {
"Accept": "application/json",
"Authorization": "Bearer $token",
});

final userDataJson = jsonDecode(userData.body);
print(userData.body);
print(userData.statusCode);

var session = Session.getSession(request);
session ??= Session.createSession(request);
session.data['user_data'] = {
'id': userDataJson['user']['id'],
'name': userDataJson['user']['global_name'] ?? userDataJson['user']['username'],
'avatar': userDataJson['user']['avatar'],
'expires_at': userDataJson['expires'],
'token': token,
};
session.expires = DateTime.now().add(Duration(seconds: tokenBodyJson['expires_in']));

return shelf.Response.seeOther("/");
}

Future<shelf.Response> _handleLogOut(shelf.Request request) async {
Session.deleteSession(request);

return shelf.Response.seeOther("/");
}

Future<shelf_router.Router> _setupRouter() async {
return shelf_router.Router()
..get("/", _sessionAware(_handleIndex))
..get("/redirect", _sessionAware(_handleRedirect))
..get("/logout", _sessionAware(_handleLogOut));
}

shelf.Handler _sessionAware(shelf.Handler inner) =>
shelf.Pipeline().addMiddleware(cookiesMiddleware()).addMiddleware(sessionMiddleware()).addHandler(inner);

Future<void> startServer() async {
final router = await _setupRouter();

final app =
const shelf.Pipeline().addMiddleware(shelf.logRequests()).addMiddleware(corsHeaders()).addHandler(router.call);

await shelf_io.serve(app, "0.0.0.0", 8088);
}
}
9 changes: 9 additions & 0 deletions lib/src/api/utils.dart → lib/src/web_app/utils.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'dart:convert';
import 'dart:io';

import 'package:mustachex/mustachex.dart';
import 'package:shelf/shelf.dart' as shelf;

shelf.Response createJsonErrorResponse(int errorCode, String errorMessage) {
Expand All @@ -11,6 +13,13 @@ shelf.Response createOkResponse(Object? body) {
return shelf.Response.ok(jsonEncode(body), headers: {"Content-Type": 'application/json'});
}

Future<shelf.Response> createTwigResponse(String name, {Map<String, dynamic>? parameters}) async {
final processor = MustachexProcessor(initialVariables: parameters);
final templateData = await File("templates/$name").readAsString();

return shelf.Response.ok(await processor.process(templateData), headers: {"Content-Type": 'text/html'});
}

shelf.Response createUnauthorizedResponse(String errorMessage) => createJsonErrorResponse(400, errorMessage);

shelf.Response createForbiddenResponse() => shelf.Response.forbidden(null);
8 changes: 8 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.4"
shelf_session:
dependency: "direct main"
description:
name: shelf_session
sha256: "5c658d16ddac1ad364d047e9a22e1023fcb383f2f32d5b621feb57c6c3ca8748"
url: "https://pub.dev"
source: hosted
version: "0.1.2"
shelf_static:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencies:
shelf: ^1.4.2
shelf_router: ^1.1.4
shelf_cors_headers: ^0.1.0
shelf_session: ^0.1.2
mustachex: ^1.0.0

dev_dependencies:
Expand Down
26 changes: 25 additions & 1 deletion templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,32 @@
<head>
<meta charset="UTF-8">
<title>Test</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
</head>
<body>
<p>Memory usage: {{memory_usage_string}}</p>
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="/">Running on Dart</a>
</div>

<div id="navbarBasicExample" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item" href="/guild">Guild</a>
</div>

<div class="navbar-end">
<div class="navbar-item">
<div class="buttons">
<a class="button is-light" href="https://discord.com/oauth2/authorize?response_type=code&client_id={{clientId}}&redirect_uri={{redirectUri}}&scope=identify">Log in</a>
{{#user_data}}
<a class="button is-light" href="/logout">Log out</a>
{{/user_data}}
</div>
</div>
</div>
</div>
</nav>

<p>Is logged in: {{user_data}}</p>
</body>
</html>

0 comments on commit 843e30e

Please sign in to comment.