Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated dependencies + small improvements #8

Merged
merged 8 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/dart.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Dart

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

# Note: This workflow uses the latest stable version of the Dart SDK.
# You can specify other versions if desired, see documentation here:
# https://github.com/dart-lang/setup-dart/blob/main/README.md
# - uses: dart-lang/setup-dart@v1
- uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603

- name: Install dependencies
run: dart pub get

- name: Check code format
run: dart format . -o none --set-exit-if-changed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool


# Uncomment this step to verify the use of 'dart format' on each commit.
# - name: Verify formatting
# run: dart format --output=none --set-exit-if-changed .

# Consider passing '--fatal-infos' for slightly stricter analysis.
- name: Analyze project source
run: dart analyze

# Your project will need to have tests in test/ and a dependency on
# package:test for this step to succeed. Note that Flutter projects will
# want to change this to 'flutter test'.
- name: Run tests
run: dart test
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.2.0

- Updated dependencies to latest versions. Including `chopper: 7.0.4` and `http: 1.1.0`.
- Added basic github action checks.
- Removed mockito in favor of mocktail.

## 0.1.2

- Add ID token to OAuth token
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Example:

/// Add the oauth authenticator and interceptor to the chopper client.
final chopperClient = ChopperClient(
baseUrl: 'https://example.com',
baseUrl: Uri.parse('https://example.com'),
authenticator: oauthChopper.authenticator(),
interceptors: [
oauthChopper.interceptor,
Expand Down
2 changes: 1 addition & 1 deletion example/oauth_chopper_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void main() {

/// Add the oauth authenticator and interceptor to the chopper client.
final chopperClient = ChopperClient(
baseUrl: Uri(host: 'https://example.com'),
baseUrl: Uri.parse('https://example.com'),
authenticator: oauthChopper.authenticator(),
interceptors: [
oauthChopper.interceptor,
Expand Down
10 changes: 7 additions & 3 deletions lib/src/oauth_chopper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ class OAuthChopper {
/// Get stored [OAuthToken].
Future<OAuthToken?> get token async {
final credentialsJson = await _storage.fetchCredentials();
return credentialsJson != null ? OAuthToken.fromJson(credentialsJson) : null;
return credentialsJson != null
? OAuthToken.fromJson(credentialsJson)
: null;
}

/// Provides an [OAuthAuthenticator] instance.
Expand All @@ -72,7 +74,8 @@ class OAuthChopper {
if (credentialsJson == null) return null;
final credentials = Credentials.fromJson(credentialsJson);
try {
final newCredentials = await credentials.refresh(identifier: identifier, secret: secret);
final newCredentials =
await credentials.refresh(identifier: identifier, secret: secret);
await _storage.saveCredentials(newCredentials.toJson());
return OAuthToken.fromCredentials(newCredentials);
} catch (e) {
Expand All @@ -88,7 +91,8 @@ class OAuthChopper {
///
/// Throws an exception if the grant fails.
Future<OAuthToken> requestGrant(OAuthGrant grant) async {
final credentials = await grant.handle(authorizationEndpoint, identifier, secret);
final credentials =
await grant.handle(authorizationEndpoint, identifier, secret);

await _storage.saveCredentials(credentials);

Expand Down
2 changes: 1 addition & 1 deletion lib/src/oauth_interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:oauth_chopper/src/extensions/request.dart';
/// OAuthInterceptor is responsible for adding 'Authorization' header to requests.
/// The header is only added if there is a token available. When no token is available no header is added.
/// Its added as a Bearer token.
class OAuthInterceptor extends RequestInterceptor {
class OAuthInterceptor implements RequestInterceptor {
OAuthInterceptor(this.oauthChopper);

final OAuthChopper oauthChopper;
Expand Down
3 changes: 2 additions & 1 deletion lib/src/oauth_token.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ class OAuthToken {
final DateTime? expiration;
final String? idToken;

bool get isExpired => expiration != null && DateTime.now().isAfter(expiration!);
bool get isExpired =>
expiration != null && DateTime.now().isAfter(expiration!);

const OAuthToken._(
this.accessToken,
Expand Down
15 changes: 7 additions & 8 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
name: oauth_chopper
description: Add and manage OAuth2 authentication for your Chopper client.
version: 0.1.2
version: 0.2.0
homepage: https://github.com/DutchCodingCompany/oauth_chopper

environment:
sdk: '>=3.0.0 <4.0.0'

dependencies:
chopper: ^6.1.3
oauth2: ^2.0.0
chopper: ^7.0.4
oauth2: ^2.0.2

dev_dependencies:
build_runner: ^2.2.1
lints: ^2.0.0
test: ^1.21.6
mockito: ^5.3.0
http: ^0.13.5
http: ^1.1.0
lints: ^2.1.1
mocktail: ^1.0.0
test: ^1.24.6
40 changes: 19 additions & 21 deletions test/oauth_authenticator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import 'dart:io';

import 'package:chopper/chopper.dart';
import 'package:http/http.dart' as http;
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:mocktail/mocktail.dart';
import 'package:oauth2/oauth2.dart';
import 'package:oauth_chopper/src/oauth_authenticator.dart';
import 'package:oauth_chopper/src/oauth_chopper.dart';
import 'package:oauth_chopper/src/oauth_token.dart';
import 'package:test/test.dart';

@GenerateMocks([OAuthChopper])
import 'oauth_authenticator_test.mocks.dart';
class MockOAuthChopper extends Mock implements OAuthChopper {}

void main() {
final mockOAuthChopper = MockOAuthChopper();
Expand All @@ -22,16 +20,16 @@ void main() {
expiration: DateTime(2022, 9, 1),
),
);
final testRequest = Request('GET', Uri(host: 'test'), Uri(host: 'test'));
final testRequest = Request('GET', Uri.parse('test'), Uri.parse('test'));
final unauthorizedResponse =
Response(http.Response('body', HttpStatus.unauthorized), 'body');
final authorizedResponse =
Response(http.Response('body', HttpStatus.accepted), 'body');

test('only refresh on unauthorized and token', () async {
// arrange
when(mockOAuthChopper.refresh()).thenAnswer((_) async => testToken);
when(mockOAuthChopper.token).thenAnswer((_) async => testToken);
when(() => mockOAuthChopper.refresh()).thenAnswer((_) async => testToken);
when(() => mockOAuthChopper.token).thenAnswer((_) async => testToken);
final authenticator = OAuthAuthenticator(mockOAuthChopper, null);
final expected = {'Authorization': 'Bearer token'};

Expand All @@ -40,59 +38,59 @@ void main() {
await authenticator.authenticate(testRequest, unauthorizedResponse);

// assert
verify(mockOAuthChopper.refresh()).called(1);
verify(() => mockOAuthChopper.refresh()).called(1);
expect(result?.headers, expected);
});

test("Don't refresh on authorized", () async {
// arrange
when(mockOAuthChopper.refresh()).thenAnswer((_) async => testToken);
when(mockOAuthChopper.token).thenAnswer((_) async => testToken);
when(() => mockOAuthChopper.refresh()).thenAnswer((_) async => testToken);
when(() => mockOAuthChopper.token).thenAnswer((_) async => testToken);
final authenticator = OAuthAuthenticator(mockOAuthChopper, null);

// act
final result =
await authenticator.authenticate(testRequest, authorizedResponse);

// assert
verifyNever(mockOAuthChopper.refresh());
verifyNever(() => mockOAuthChopper.refresh());
expect(result, null);
});

test("Don't refresh on token not available", () async {
// arrange
when(mockOAuthChopper.refresh()).thenAnswer((_) async => testToken);
when(mockOAuthChopper.token).thenAnswer((_) async => null);
when(() => mockOAuthChopper.refresh()).thenAnswer((_) async => testToken);
when(() => mockOAuthChopper.token).thenAnswer((_) async => null);
final authenticator = OAuthAuthenticator(mockOAuthChopper, null);

// act
final result =
await authenticator.authenticate(testRequest, unauthorizedResponse);

// assert
verifyNever(mockOAuthChopper.refresh());
verifyNever(() => mockOAuthChopper.refresh());
expect(result, null);
});

test("Don't add headers on failed refresh", () async {
// arrange
when(mockOAuthChopper.refresh()).thenAnswer((_) async => null);
when(mockOAuthChopper.token).thenAnswer((_) async => testToken);
when(() => mockOAuthChopper.refresh()).thenAnswer((_) async => null);
when(() => mockOAuthChopper.token).thenAnswer((_) async => testToken);
final authenticator = OAuthAuthenticator(mockOAuthChopper, null);

// act
final result =
await authenticator.authenticate(testRequest, unauthorizedResponse);

// assert
verify(mockOAuthChopper.refresh()).called(1);
verify(() => mockOAuthChopper.refresh()).called(1);
expect(result, null);
});

test("Exception thrown if onError is null", () async {
// arrange
when(mockOAuthChopper.refresh()).thenThrow(FormatException('failed'));
when(mockOAuthChopper.token).thenAnswer((_) async => testToken);
when(() => mockOAuthChopper.refresh()).thenThrow(FormatException('failed'));
when(() => mockOAuthChopper.token).thenAnswer((_) async => testToken);
final authenticator = OAuthAuthenticator(mockOAuthChopper, null);

// act
Expand All @@ -106,8 +104,8 @@ void main() {
test("Exception not thrown if onError is supplied", () async {
// arrange
FormatException? result;
when(mockOAuthChopper.refresh()).thenThrow(FormatException('failed'));
when(mockOAuthChopper.token).thenAnswer((_) async => testToken);
when(() => mockOAuthChopper.refresh()).thenThrow(FormatException('failed'));
when(() => mockOAuthChopper.token).thenAnswer((_) async => testToken);
final authenticator = OAuthAuthenticator(
mockOAuthChopper, (e, s) => result = e as FormatException);

Expand Down
98 changes: 0 additions & 98 deletions test/oauth_authenticator_test.mocks.dart

This file was deleted.

Loading