Skip to content

Commit

Permalink
exp: onCall
Browse files Browse the repository at this point in the history
  • Loading branch information
alextekartik committed Jul 3, 2024
1 parent 2d86b1f commit e479c8b
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 57 deletions.
2 changes: 1 addition & 1 deletion auth_node/lib/src/node/auth_node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class UserRecordNode implements UserRecord {

/// Node implementation
class DecodedIdTokenNode implements DecodedIdToken {
final node.DecodedIdToken nativeInstance;
final node.JSDecodedIdToken nativeInstance;

DecodedIdTokenNode(this.nativeInstance);

Expand Down
18 changes: 9 additions & 9 deletions auth_node/lib/src/node/auth_node_js_interop.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ extension AuthExt on Auth {
/// Verifies a Firebase ID token (JWT).
///
/// If the token is valid, the returned js.JSPromise is fulfilled with an instance of
/// [DecodedIdToken]; otherwise, the js.JSPromise is rejected. An optional flag can
/// [JSDecodedIdToken]; otherwise, the js.JSPromise is rejected. An optional flag can
/// be passed to additionally check whether the ID token was revoked.
@js.JS('jsVerifyIdToken')
external js.JSPromise<DecodedIdToken> jsVerifyIdToken(String idToken,
external js.JSPromise<JSDecodedIdToken> jsVerifyIdToken(String idToken,
[bool? checkRevoked]);
}

Expand Down Expand Up @@ -319,9 +319,9 @@ extension ListUsersResultExt on ListUsersResult {

/// Interface representing a decoded Firebase ID token, returned from the
/// [AuthModule.verifyIdToken] method.
extension type DecodedIdToken._(js.JSObject _) implements js.JSObject {}
extension type JSDecodedIdToken._(js.JSObject _) implements js.JSObject {}

extension DecodedIdTokenExt on DecodedIdToken {
extension JSDecodedIdTokenExt on JSDecodedIdToken {
/// The audience for which this token is intended.
///
/// This value is a string equal to your Firebase project ID, the unique
Expand Down Expand Up @@ -353,7 +353,7 @@ extension DecodedIdTokenExt on DecodedIdToken {
///
/// This data is provided by the Firebase Authentication service and is a
/// reserved claim in the ID token.
external FirebaseSignInInfo get firebase;
external JSFirebaseSignInInfo get firebase;

/// The ID token's issued-at time, in seconds since the Unix epoch.
///
Expand Down Expand Up @@ -385,9 +385,9 @@ extension DecodedIdTokenExt on DecodedIdToken {
external String get uid;
}

extension type FirebaseSignInInfo._(js.JSObject _) implements js.JSObject {}
extension type JSFirebaseSignInInfo._(js.JSObject _) implements js.JSObject {}

extension FirebaseSignInInfoExt on FirebaseSignInInfo {
extension FirebaseSignInInfoExt on JSFirebaseSignInInfo {
/// Provider-specific identity details corresponding to the provider used to
/// sign in the user.
external js.JSObject? get identities;
Expand Down Expand Up @@ -486,10 +486,10 @@ extension AuthExt2 on Auth {
/// Verifies a Firebase ID token (JWT).
///
/// If the token is valid, the returned [Future] is completed with an instance
/// of [DecodedIdToken]; otherwise, the future is completed with an error.
/// of [JSDecodedIdToken]; otherwise, the future is completed with an error.
/// An optional flag can be passed to additionally check whether the ID token
/// was revoked.
Future<DecodedIdToken> verifyIdToken(String idToken, [bool? checkRevoked]) {
Future<JSDecodedIdToken> verifyIdToken(String idToken, [bool? checkRevoked]) {
if (checkRevoked != null) {
return jsVerifyIdToken(idToken, checkRevoked).toDart;
} else {
Expand Down
43 changes: 43 additions & 0 deletions functions_node/lib/src/node/call_request_node.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'dart:js_interop';

import 'package:tekartik_firebase_auth/auth.dart';
import 'package:tekartik_firebase_auth_node/src/node/auth_node.dart' // ignore: implementation_imports
as impl;
import 'package:tekartik_firebase_functions/firebase_functions.dart';
import 'package:tekartik_firebase_functions_node/src/node/firebase_functions_https_node_js_interop.dart'
as js;

class CallRequestNode with CallRequestMixin implements CallRequest {
final js.JSCallableRequest nativeInstance;

@override
late final Object? data = nativeInstance.data?.dartify();

@override
late final CallContext context = CallContextNode(nativeInstance);

CallRequestNode(this.nativeInstance);
}

class CallContextNode with CallContextMixin implements CallContext {
final js.JSCallableRequest nativeInstance;

CallContextNode(this.nativeInstance);

@override
late final CallContextAuth? auth = CallContextAuthNode(nativeInstance);
}

class CallContextAuthNode with CallContextAuthMixin implements CallContextAuth {
final js.JSCallableRequest nativeInstance;

CallContextAuthNode(this.nativeInstance);

@override
String? get uid => nativeInstance.auth.uid;

@override
DecodedIdToken? get token {
return impl.DecodedIdTokenNode(nativeInstance.auth.token);
}
}
94 changes: 94 additions & 0 deletions functions_node/lib/src/node/firebase_functions_https_node.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import 'dart:async';
import 'dart:js_interop' as js;

import 'package:tekartik_firebase_functions/firebase_functions.dart';
import 'package:tekartik_firebase_functions_node/src/node/firebase_functions_https_node_js_interop.dart'
as node;

import 'call_request_node.dart';
import 'express_http_request_node.dart';
import 'firebase_functions_node.dart';

class HttpsFunctionsNode
with HttpsFunctionsDefaultMixin
implements HttpsFunctions {
final FirebaseFunctionsNode functions;
final node.JSHttpsFunctions nativeInstance;

HttpsFunctionsNode(this.functions, this.nativeInstance);

@override
HttpsFunction onRequest(RequestHandler handler,
{HttpsOptions? httpsOptions}) {
void handleRequest(
node.JSHttpsRequest request, node.JSHttpsResponse response) {
var expressRequest = ExpressHttpRequestNode(request, response);
handler(expressRequest);
}

return HttpsFunctionNode(
functions,
nativeInstance.onRequest(
options: toNodeHttpsOptionsOrNull(httpsOptions),
handler: handleRequest));
}

@override
HttpsCallableFunction onCall(CallHandler handler,
{HttpsCallableOptions? callableOptions}) {
FutureOr<Object?> handleCall(node.JSCallableRequest request) {
var requestNode = CallRequestNode(request);
return handler(requestNode);
}

return HttpsCallableFunctionNode(
functions,
nativeInstance.onCall(
options: toNodeCallableOptionsOrNull(callableOptions),
handler: handleCall));
}
}

class HttpsFunctionNode extends FirebaseFunctionNode implements HttpsFunction {
@override
final node.JSHttpsFunction nativeInstance;

HttpsFunctionNode(super.firebaseFunctionsNode, this.nativeInstance);
}

class HttpsCallableFunctionNode extends FirebaseFunctionNode
implements HttpsCallableFunction {
@override
final node.JSCallableFunction nativeInstance;

HttpsCallableFunctionNode(super.firebaseFunctionsNode, this.nativeInstance);
}

node.JSHttpsOptions? toNodeHttpsOptionsOrNull(HttpsOptions? httpsOptions) {
if (httpsOptions == null) {
return null;
}
return toNodeHttpsOptions(httpsOptions);
}

node.JSHttpsOptions toNodeHttpsOptions(HttpsOptions httpsOptions) {
return node.JSHttpsOptions(
region: httpsOptions.region, cors: httpsOptions.cors?.toJS);
}

node.JSCallableOptions? toNodeCallableOptionsOrNull(
HttpsCallableOptions? callableOptions) {
if (callableOptions == null) {
return null;
}
return toNodeCallableOptions(callableOptions);
}

node.JSCallableOptions toNodeCallableOptions(
HttpsCallableOptions callableOptions) {
return node.JSCallableOptions(
consumeAppCheckToken: callableOptions.consumeAppCheckToken,
enforceAppCheck: callableOptions.enforceAppCheck,
region: callableOptions.region,
cors: callableOptions.cors?.toJS);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// Copyright (c) 2018, Anatoly Pulyaevskiy. All rights reserved. Use of this source code
// is governed by a BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:js_interop' as js;

// ignore: implementation_imports
import 'package:tekartik_firebase_auth_node/src/node/auth_node_js_interop.dart'
as js;
import 'package:tekartik_firebase_functions_node/src/import_common.dart';

import 'firebase_functions_node_js_interop.dart';

extension type JSHttpsFunctions._(js.JSObject _) implements js.JSObject {}
Expand All @@ -22,6 +25,13 @@ extension JSHttpsFunctionsExt on JSHttpsFunctions {
@js.JS('onRequest')
external JSHttpsFunction _onRequestNoOptions(_JSHttpsHandler handler);

@js.JS('onCall')
external JSCallableFunction _onCall(
JSCallableOptions options, _JSCallableHandler handler);

@js.JS('onCall')
external JSHttpsFunction _onCallNoOptions(_JSCallableHandler handler);

JSHttpsFunction onRequest(
{JSHttpsOptions? options, required HttpsHandler handler}) {
js.JSAny? jsHandler(JSHttpsRequest request, JSHttpsResponse response) {
Expand All @@ -41,10 +51,27 @@ extension JSHttpsFunctionsExt on JSHttpsFunctions {
return _onRequest(options, jsHandler.toJS);
}
}

JSCallableFunction onCall(
{JSCallableOptions? options, required CallableHandler handler}) {
js.JSAny jsHandler(JSCallableRequest request) {
var result = handler(request);
if (result is Future) {
return result.then((value) => (value as Object?)?.jsify()).toJS;
} else {
return result.jsify()!;
}
}

if (options == null) {
return _onCallNoOptions(jsHandler.toJS);
} else {
return _onCall(options, jsHandler.toJS);
}
}
}

// An express request with the wire format representation of the request body.
//
/// An express request with the wire format representation of the request body.
extension type JSHttpsRequest._(js.JSObject _) implements js.JSObject {}

extension JSHttpsRequestExt on JSHttpsRequest {
Expand Down Expand Up @@ -116,11 +143,13 @@ extension type JSHttpsResponse._(js.JSObject _) implements js.JSObject {
extension JSHttpsResponseExt on JSHttpsResponse {}

typedef JSHttpsFunction = js.JSFunction;
typedef JSCallableFunction = js.JSFunction;
typedef _JSHttpsHandler = js.JSFunction;
typedef _JSCallableHandler = js.JSFunction;

typedef HttpsHandler = FutureOr<void> Function(
JSHttpsRequest request, JSHttpsResponse response);

typedef CallableHandler = FutureOr<Object?> Function(JSCallableRequest request);
typedef JSFirebaseFunction = js.JSFunction;

/// Options that can be set on an onRequest HTTPS function.
Expand All @@ -136,6 +165,26 @@ extension type JSHttpsOptions._(js.JSObject _) implements JSGlobalOptions {
int? timeoutSeconds});
}

/// Options that can be set on an onRequest HTTPS function.
///
/// export interface HttpsOptions extends Omit<GlobalOptions, "region">
extension type JSCallableOptions._(js.JSObject _) implements JSHttpsOptions {
/// Options
external factory JSCallableOptions({
String? region,
String? memory,
int? concurrency,
js.JSAny? cors,
int? timeoutSeconds,

/// Determines whether Firebase App Check token is consumed on request. Defaults to false.
bool? consumeAppCheckToken,

/// Determines whether Firebase AppCheck is enforced. When true, requests with invalid tokens autorespond with a 401 (Unauthorized) error. When false, requests with invalid tokens set event.app to undefiend.
bool? enforceAppCheck,
});
}

extension JSHttpsOptionsExt on JSHttpsOptions {
/// string | boolean | RegExp | Array<string | RegExp>
///
Expand All @@ -146,3 +195,22 @@ extension JSHttpsOptionsExt on JSHttpsOptions {
/// otherwise.
external js.JSAny? get cors;
}

/// Metadata about the authorization used to invoke a function.
extension type JSAuthData._(js.JSObject _) implements js.JSObject {}

extension JSAuthDataExt on JSAuthData {
external js.JSDecodedIdToken get token;
external String get uid;
}

/// An express request with the wire format representation of the request body.
extension type JSCallableRequest._(js.JSObject _) implements js.JSObject {}

extension JSCallableRequestExt on JSCallableRequest {
/// The result of decoding and verifying a Firebase Auth ID token.
external JSAuthData get auth;

/// The parameters used by a client when calling this function.
external js.JSAny? get data;
}
44 changes: 1 addition & 43 deletions functions_node/lib/src/node/firebase_functions_node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import 'package:tekartik_firebase_functions_node/src/node/firebase_functions_htt
import 'package:tekartik_firebase_functions_node/src/node/firebase_functions_node_js_interop.dart'
as node;

import 'express_http_request_node.dart';
import 'firebase_functions_firestore_node.dart';
import 'firebase_functions_https_node.dart';
import 'firebase_functions_scheduler_node.dart';

final firebaseFunctionsNode = FirebaseFunctionsNode();
Expand Down Expand Up @@ -41,29 +41,6 @@ class FirebaseFunctionsNode
}
}

class HttpsFunctionsNode with HttpsFunctionsMixin implements HttpsFunctions {
final FirebaseFunctionsNode functions;
final node.JSHttpsFunctions nativeInstance;

HttpsFunctionsNode(this.functions, this.nativeInstance);

@override
HttpsFunction onRequest(RequestHandler handler,
{HttpsOptions? httpsOptions}) {
void handleRequest(
node.JSHttpsRequest request, node.JSHttpsResponse response) {
var expressRequest = ExpressHttpRequestNode(request, response);
handler(expressRequest);
}

return HttpsFunctionNode(
functions,
nativeInstance.onRequest(
options: toNodeHttpsOptionsOrNull(httpsOptions),
handler: handleRequest));
}
}

abstract class FirebaseFunctionNode implements FirebaseFunction {
final FirebaseFunctionsNode firebaseFunctionsNode;

Expand All @@ -72,25 +49,6 @@ abstract class FirebaseFunctionNode implements FirebaseFunction {
node.JSFirebaseFunction get nativeInstance;
}

class HttpsFunctionNode extends FirebaseFunctionNode implements HttpsFunction {
@override
final node.JSHttpsFunction nativeInstance;

HttpsFunctionNode(super.firebaseFunctionsNode, this.nativeInstance);
}

node.JSHttpsOptions? toNodeHttpsOptionsOrNull(HttpsOptions? httpsOptions) {
if (httpsOptions == null) {
return null;
}
return toNodeHttpsOptions(httpsOptions);
}

node.JSHttpsOptions toNodeHttpsOptions(HttpsOptions httpsOptions) {
return node.JSHttpsOptions(
region: httpsOptions.region, cors: httpsOptions.cors?.toJS);
}

class _ParamsNode implements Params {
final FirebaseFunctionsNode functions;
final node.JSParams _params;
Expand Down

0 comments on commit e479c8b

Please sign in to comment.