Skip to content
This repository was archived by the owner on Feb 21, 2021. It is now read-only.

Commit e97489c

Browse files
authored
Add authentication. (#2)
* Add FirebaseAuth. * Bump. * Oops.
1 parent 3d27ea5 commit e97489c

File tree

7 files changed

+300
-20
lines changed

7 files changed

+300
-20
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.1.1
2+
3+
- Removed a `print` statement that was always occurring.
4+
- Added a high-level `FirebaseAuth` class, and Google sign-in.
5+
- Added `IfFirebaseAuthDirective`.
6+
17
## 0.1.0
28

39
- Initial commit of `GoogleSignInComppnent`.

README.md

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010

1111
* [Install](#install)
1212
* [Usage](#usage)
13-
* [Components](#components)
13+
* [Services](#services)
14+
* [FirebaseAuth](#firebase-auth)
15+
* [Directives](#directives)
1416
* [GoogleSignInComponent](#google-sign-in-component)
17+
* [IfFirebaseAuthDirective](#if-firebase-auth-directive)
1518
* [Contributing](#contributing)
1619
* [Testing](#testing)
1720

@@ -38,6 +41,38 @@ To get started, you need to, at minimum, include the Firebase SDK:
3841

3942
## Usage
4043

44+
### Services
45+
46+
#### FirebaseAuth
47+
48+
A high-level authentication service. First setup for dependency injection:
49+
50+
```dart
51+
import 'package:angular2/angular2.dart';
52+
import 'package:angular2/platform/browser.dart';
53+
import 'package:angular_fire/angular_fire.dart';
54+
import 'package:firebase/firebase.dart' as sdk;
55+
56+
main() {
57+
bootstrap(AngularFireExample, <dynamic>[
58+
provide(
59+
FirebaseAuth,
60+
useValue: new FirebaseAuth(
61+
sdk.initializeApp(
62+
apiKey: '...',
63+
authDomain: '...',
64+
databaseURL: '...',
65+
storageBucket: '...',
66+
),
67+
),
68+
),
69+
]);
70+
}
71+
```
72+
73+
Then inject into your app and use. See [GoogleSignInComponent](#google-sign-in-component)
74+
below for an example.
75+
4176
### Components
4277

4378
#### GoogleSignInComponent
@@ -48,8 +83,6 @@ Displays a rendered sign in box for Google authentication that follows the
4883
<img src="https://cloud.githubusercontent.com/assets/168174/26565270/896f1ac6-449e-11e7-8e7a-967547e5fb65.png" height="600" />
4984

5085
```dart
51-
import 'dart:html';
52-
5386
import 'package:angular2';
5487
import 'package:angular_fire/angular_fire.dart';
5588
@@ -59,16 +92,15 @@ import 'package:angular_fire/angular_fire.dart';
5992
GoogleSignInComponent,
6093
],
6194
template: r'''
62-
<google-sign-in (trigger)="onTrigger()">
63-
</google-sign-in>
64-
65-
<google-sign-in [useDarkTheme]="true" (trigger)="onTrigger()">
95+
<google-sign-in (trigger)="signIn()">
6696
</google-sign-in>
6797
''',
6898
)
6999
class AngularFireExample {
100+
final FirebaseAuth _auth;
101+
70102
void onTrigger() {
71-
window.alert('Pressed!');
103+
_auth.signIn();
72104
}
73105
}
74106
```
@@ -78,6 +110,27 @@ class AngularFireExample {
78110
`googleSignInAssetPath` token at `bootstrap` time to configure the location of
79111
your assets - for example on an external CDN.
80112

113+
#### IfFirebaseAuthDirective
114+
115+
Like `ngIf`, but shows content if the value matches the current authentication:
116+
117+
```html
118+
<div *ifFirebaseAuth="true; let currentUser = currentUser">
119+
Logged in as: {{currentUser.displayName}}.
120+
<button (click)="signOut()">Sign Out</button>
121+
</div>
122+
123+
<div *ifFirebaseAuth="false">
124+
Waiting for sign in...
125+
126+
<br>
127+
128+
<google-sign-in
129+
(trigger)="signIn()">
130+
</google-sign-in>
131+
</div>
132+
```
133+
81134
## Contributing
82135

83136
We welcome a diverse set of contributions, including, but not limited to:

lib/angular_fire.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44

55
export 'src/components/google_sign_in.dart'
66
show googleSignInAssetPath, googleSignInDarkTheme, GoogleSignInComponent;
7+
8+
export 'src/directives/firebase_auth.dart'
9+
show FirebaseAuth, FirebaseUser, IfFirebaseAuthDirective;

lib/src/components/google_sign_in.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ class GoogleSignInComponent {
147147
const prefix = 'btn_google_signin_';
148148
final asset = '$prefix${_useDarkTheme ? 'dark' : 'light'}_${_status}_web';
149149
final suffix = _isHighResolution ? '@2x' : '';
150-
print('$asset$suffix');
151150
_element.style.backgroundImage = 'url($_assetPath$asset$suffix.png)';
152151
}
153152

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Copyright 2017, Google Inc. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'package:angular2/angular2.dart';
8+
import 'package:firebase/firebase.dart' as sdk;
9+
10+
/// An injectable service representing authentication with Firebase.
11+
///
12+
/// The default implementation requires providing a [sdk.App] object:
13+
/// ```dart
14+
/// import 'package:angular2/angular2.dart';
15+
/// import 'package:angular2/platform/browser.dart';
16+
/// import 'package:firebase/firebase.dart' as sdk;
17+
///
18+
/// bootstrap(AngularFireExample, [
19+
/// provide(FirebaseAuth, useValue: new FirebaseAuth(
20+
/// sdk.initializeApp(
21+
/// ...
22+
/// ),
23+
/// )),
24+
/// ]);
25+
/// ````
26+
@Injectable()
27+
abstract class FirebaseAuth {
28+
factory FirebaseAuth(sdk.App app) = _SdkFirebaseAuth;
29+
30+
/// Returns a stream of authenticated users.
31+
///
32+
/// A value of `null` should be treated as not signed in.
33+
Stream<FirebaseUser> currentUser();
34+
35+
/// Returns a future that completes after authenticated.
36+
Future<FirebaseUser> googleSignIn();
37+
38+
/// Sign out of any authenticated account.
39+
Future<Null> signOut();
40+
}
41+
42+
class _SdkFirebaseAuth implements FirebaseAuth {
43+
static final sdk.AuthProvider _googleAuth = new sdk.GoogleAuthProvider();
44+
45+
final sdk.App _app;
46+
final _onUserChanged = new StreamController<FirebaseUser>.broadcast();
47+
48+
FirebaseUser _currentUser;
49+
50+
_SdkFirebaseAuth(this._app) {
51+
_app.auth().onAuthStateChanged.listen((event) {
52+
final user = event.user;
53+
_currentUser = user != null ? new FirebaseUser._fromSdk(user) : null;
54+
_onUserChanged.add(_currentUser);
55+
});
56+
}
57+
58+
@override
59+
Stream<FirebaseUser> currentUser() async* {
60+
yield _currentUser;
61+
yield* _onUserChanged.stream;
62+
}
63+
64+
@override
65+
Future<FirebaseUser> googleSignIn() async {
66+
final user = await _app.auth().signInWithPopup(_googleAuth);
67+
return new FirebaseUser._fromSdk(user.user);
68+
}
69+
70+
@override
71+
Future<Null> signOut() async {
72+
await _app.auth().signOut();
73+
}
74+
}
75+
76+
/// Represents a user that is authenticated with Firebase.
77+
class FirebaseUser {
78+
final String displayName;
79+
final String emailAddress;
80+
final String userId;
81+
final String photoUrl;
82+
final String providerId;
83+
84+
factory FirebaseUser._fromSdk(sdk.User user) {
85+
return new FirebaseUser(
86+
displayName: user.displayName,
87+
emailAddress: user.email,
88+
userId: user.uid,
89+
photoUrl: user.photoURL,
90+
providerId: user.providerId,
91+
);
92+
}
93+
94+
const FirebaseUser({
95+
this.displayName,
96+
this.emailAddress,
97+
this.userId,
98+
this.photoUrl,
99+
this.providerId,
100+
});
101+
}
102+
103+
/// Conditionally shows content based on authentication status with Firebase.
104+
///
105+
/// ```html
106+
/// <div *ifFirebaseAuth="true">
107+
/// Logged in!
108+
/// </div>
109+
/// <div *ifFirebaseAuth="false">
110+
/// Logged out!
111+
/// </div>
112+
/// ````
113+
///
114+
/// **NOTE**: Only a static value of "true" or "false" is supported.
115+
///
116+
/// You can get a handle to the logged in user:
117+
///
118+
/// ```html
119+
/// <div *ifFirebaseAuth="true; let currentUser = currentUser">
120+
/// Logged in as {{currentUser.displayName}}!
121+
/// </div>
122+
/// ```
123+
@Directive(
124+
selector: '[ifFirebaseAuth]',
125+
)
126+
class IfFirebaseAuthDirective implements OnDestroy, OnInit {
127+
final FirebaseAuth _authService;
128+
final TemplateRef _templateRef;
129+
final ViewContainerRef _viewContainerRef;
130+
131+
bool _checkCondition;
132+
bool _lastCondition;
133+
FirebaseUser _currentUser;
134+
StreamSubscription<FirebaseUser> _userSub;
135+
136+
IfFirebaseAuthDirective(
137+
this._authService,
138+
this._templateRef,
139+
this._viewContainerRef,
140+
);
141+
142+
@Input()
143+
set ifFirebaseAuth(bool newCondition) {
144+
_checkCondition = newCondition;
145+
_toggle(_checkCondition ? _currentUser != null : _currentUser == null);
146+
}
147+
148+
@override
149+
void ngOnDestroy() {
150+
_userSub.cancel();
151+
}
152+
153+
@override
154+
void ngOnInit() {
155+
_userSub = _authService.currentUser().listen((user) {
156+
_currentUser = user;
157+
_toggle(_checkCondition ? _currentUser != null : _currentUser == null);
158+
});
159+
}
160+
161+
void _toggle(bool show) {
162+
if (!show) {
163+
_signedOut();
164+
} else {
165+
_signedIn();
166+
}
167+
}
168+
169+
void _signedIn() {
170+
if (_lastCondition == true) return;
171+
_viewContainerRef
172+
.createEmbeddedView(_templateRef)
173+
.setLocal('currentUser', _currentUser);
174+
_lastCondition = true;
175+
}
176+
177+
void _signedOut() {
178+
if (_lastCondition == false) return;
179+
_viewContainerRef.clear();
180+
_lastCondition = false;
181+
}
182+
}

pubspec.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: angular_fire
22
description: >
33
Unofficial library for AngularDart and Firebase.
4-
version: 0.1.0
4+
version: 0.1.1
55
authors:
66
- Matan Lurey <matanl@google.com>
77
homepage: https://github.com/matanlurey/angular_fire
@@ -21,7 +21,10 @@ dev_dependencies:
2121

2222
transformers:
2323
# Ahead-of-time compilation (required in AngularDart ^4.0.0).
24-
- angular2/transform/codegen
24+
- angular2/transform/codegen:
25+
# No longer required in ^4.0.0.
26+
resolved_identifiers:
27+
App: package:firebase/firebase.dart
2528

2629
# These transformers are only invoked when using this package itself.
2730
- angular2/transform/reflection_remover:

0 commit comments

Comments
 (0)