Skip to content

Commit

Permalink
All unit tests passing.
Browse files Browse the repository at this point in the history
  • Loading branch information
bsutton committed Nov 21, 2022
1 parent 80ed4ea commit 7a34168
Show file tree
Hide file tree
Showing 45 changed files with 1,346 additions and 696 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ onepub.token.yaml
test/test_settings.yaml
bin/onepub
bin/opub
pubspec_overrides.yaml
pubspec_overrides.yaml
.failed_tracker.bak
stable-cli-blog.md
8 changes: 8 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,5 +130,13 @@
"console": "terminal"
},

{
"name": "test ct auth",
"type": "dart",
"request": "launch",
"program": "/home/bsutton/git/onepub/onepub/tool/critical_test/pre_hook/auth.dart",
"console": "terminal"
},

]
}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 3.0.0
BREAKING: the REST API used by the export command has change the name of its end point.
An upgrade of the CLI tooling to 3.x is required.
# 2.0.4
- upgraded to scope 3.0.0 as need a bug fix for async calls to Scope.run (it wouldn't wait). This required an upgrade to dcli 1.21.0 as it dependes on scope 3.0.0
- Added additional tests for the import command - still not fully tested.
Expand Down
7 changes: 7 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
include: package:lint_hard/all.yaml
# include: package:lints/recommended.yaml


analyzer:
# language:
# strict-casts: true
# strict-inference: true
# strict-raw-types: true

exclude:
- lib/src/pub
6 changes: 0 additions & 6 deletions bin/onepub.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,9 @@
* licensed under the GPL v2.
* Written by Brett Sutton <[email protected]>, Jan 2022
*/
import 'package:dcli/dcli.dart';
import 'package:onepub/src/entry_point.dart';
import 'package:onepub/src/my_runner.dart';
import 'package:onepub/src/version/version.g.dart';

Future<void> main(List<String> arguments) async {
print(orange('OnePub version: $packageVersion '));

print('');

await entrypoint(arguments, CommandSet.onepub, 'onepub');
}
41 changes: 32 additions & 9 deletions lib/src/api/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import 'dart:io';
import 'package:pub_semver/pub_semver.dart';

import '../exceptions.dart';
import '../util/role_enum.dart';
import '../util/send_command.dart';
import '../version/version.g.dart';
import 'auth_response.dart';
import 'logout.dart';
import 'member_create.dart';
import 'member_response.dart';
import 'onepub_token.dart';
import 'organisation.dart';
import 'status.dart';
Expand Down Expand Up @@ -61,9 +63,9 @@ dart pub global activate onepub

/// Fetches the [OnePubToken] for the member whos email
/// address is [memberEmail].
/// The member must be logged in to the cli.
Future<OnePubToken> fetchMemberToken(String memberEmail) async {
final endpoint = 'member/token/$memberEmail';
/// Only an Administrator can export another person token.
Future<OnePubToken> exportMemberToken(String memberEmail) async {
final endpoint = 'member/exportToken/$memberEmail';
final response =
await sendCommand(command: endpoint, commandType: CommandType.cli);

Expand All @@ -79,7 +81,7 @@ dart pub global activate onepub
// So we paass the auth header directly.
final headers = <String, String>{}..addAll({'authorization': onepubToken});

const endpoint = '/organisation/token';
const endpoint = '/organisation/details';

final response = await sendCommand(
command: endpoint,
Expand All @@ -90,8 +92,20 @@ dart pub global activate onepub
return Organisation(response);
}

/// Fetches the member details associated with the [onepubTokenOfTargetMember]
Future<MemberResponse> fetchMember(
String onepubTokenOfTargetMember,
) async {
final endpoint = '/member/details/$onepubTokenOfTargetMember';

final response =
await sendCommand(command: endpoint, commandType: CommandType.cli);

return MemberResponse(response, onepubTokenOfTargetMember);
}

Future<Organisation> fetchOrganisationById(String obfuscatedId) async {
final endpoint = 'organisation/$obfuscatedId';
final endpoint = 'organisation/details/$obfuscatedId';
final response =
await sendCommand(command: endpoint, commandType: CommandType.cli);

Expand All @@ -107,10 +121,16 @@ dart pub global activate onepub
await sendCommand(command: endpoint, commandType: CommandType.cli);
}

/// Creates a member which belongs to the same organisation
/// as the current logged in user.
/// The user must be a SystemAdministrator to make this call.
Future<MemberCreate> createMember(
String userEmail, String firstname, String lastname) async {
{required String userEmail,
required String firstname,
required String lastname,
required RoleEnum role}) async {
final endpoint =
'member/create?email=$userEmail&firstname=$firstname&lastname=$lastname';
'member/create?email=$userEmail&firstname=$firstname&lastname=$lastname&role=${role.name}';
final response =
await sendCommand(command: endpoint, commandType: CommandType.cli);

Expand All @@ -119,10 +139,13 @@ dart pub global activate onepub

/// Fetches the list of published version for [packageName]
Future<Versions> fetchVersions(
String obsfucatedOrganisationId, String packageName) async {
final endpoint = '$obsfucatedOrganisationId/api/packages/$packageName';
String obfuscatedOrganisationId, String packageName) async {
final endpoint = '$obfuscatedOrganisationId/api/packages/$packageName';
final response =
await sendCommand(command: endpoint, commandType: CommandType.pub);
if (!response.success) {
throw APIException(response.errorMessage);
}

return Versions(response);
}
Expand Down
21 changes: 21 additions & 0 deletions lib/src/api/member.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import '../util/role_enum.dart';

class Member {
Member({
required this.email,
required this.firstname,
required this.lastname,
required this.roles,
required this.onepubToken,
required this.organisationName,
required this.obfuscatedOrganisationId,
});

String email;
String firstname;
String lastname;
Set<RoleEnum> roles;
String organisationName;
String obfuscatedOrganisationId;
String onepubToken;
}
32 changes: 30 additions & 2 deletions lib/src/api/member_create.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:io';

import '../exceptions.dart';
import '../util/send_command.dart';

class MemberCreate {
Expand All @@ -12,12 +13,39 @@ class MemberCreate {

if (!response.success) {
errorMessage = response.data['message']! as String;
} else {
email = extractField(response, 'email');
firstname = extractField(response, 'firstname');
lastname = extractField(response, 'lastname');
role = extractField(response, 'lastname');
organisationName = extractField(response, 'organisationName');
obfuscateOrganisationId =
extractField(response, 'obfuscateOrganisationId');
}
}

String extractField(EndpointResponse response, String field) {
final value = response.data[field];
if (value == null) {
throw APIException("Missing field '$field");
}

if (value is! String) {
throw APIException("Invalid type for '$field', expected a String, "
'received a ${value.runtimeType}');
}

return value;
}

late final bool _success;
late final String name;
late final String obfuscatedId;

late final String email;
late final String firstname;
late final String lastname;
late final String role;
late final String organisationName;
late final String obfuscateOrganisationId;

bool get success => _success;

Expand Down
83 changes: 83 additions & 0 deletions lib/src/api/member_response.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import 'dart:io';

import '../util/role_enum.dart';
import '../util/send_command.dart';
import 'member.dart';

class MemberResponse {
MemberResponse(EndpointResponse response, this.onepubToken) {
_success = response.success;

if (response.status == HttpStatus.notFound) {
notFound = true;
}

if (!response.success) {
_errorMessage = response.data['message']! as String;
} else {
email = response.data['email'] as String? ?? '';
firstname = response.data['firstname'] as String? ?? '';
lastname = response.data['lastname'] as String? ?? '';
roles = jsonToSet(response.data['roles']);
organisationName = response.data['organisationName'] as String? ?? '';
obfuscatedOrganisationId =
response.data['obfuscateOrganisationId'] as String? ?? '';
}
}

Set<T> jsonToSet<T>(Object? responseData) {
final temp = responseData as List? ?? <dynamic>[];
final set = <T>{};
for (final tmp in temp) {
set.add(tmp as T);
}
return set;
}

List<T> jsonToList<T>(Object? responseData) {
final temp = responseData as List? ?? <dynamic>[];
final list = <T>[];
for (final tmp in temp) {
list.add(tmp as T);
}
return list;
}

late final bool _success;

final String onepubToken;
late final String email;
late final String firstname;
late final String lastname;
late final Set<String> roles;
late final String organisationName;
late final String obfuscatedOrganisationId;

bool get success => _success;

/// If success is false then you can check this field
/// to see if it failed because the organisation wasn't found
/// if this is false then a more serious error occured
bool notFound = false;

/// if [success] is false this will contain the error message.
late final String? _errorMessage;

String get errorMessage => _errorMessage ?? '';

Member toMember() {
final enumRoles = <RoleEnum>{};

for (final role in roles) {
enumRoles.add(RoleEnumHelper.byName(role));
}
return Member(
onepubToken: onepubToken,
email: email,
firstname: firstname,
lastname: lastname,
roles: enumRoles,
organisationName: organisationName,
obfuscatedOrganisationId: obfuscatedOrganisationId);
}
}
1 change: 1 addition & 0 deletions lib/src/api/versions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Versions {
}

if (!response.success) {

errorMessage = response.data['message']! as String;
} else {
name = response.data['name'] as String? ?? '';
Expand Down
29 changes: 14 additions & 15 deletions lib/src/commands/doctor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,22 @@ class DoctorCommand extends Command<int> {

@override
Future<int> run() async {
await withSettings(() async {
_printPlatform();
_printURLs();
_printEnvironment();
_printShell();

tokenStatus();
await _status();
});
_printPlatform();
_printURLs();
_printEnvironment();
_printShell();

tokenStatus();
await _status();
return 0;
}

void _printURLs() {
print('');

print(blue('\nURLs'));
_colprint(['Web site:', OnePubSettings.use.onepubWebUrl]);
_colprint(['API endpoint:', OnePubSettings.use.onepubApiUrl]);
_colprint(['Web site:', OnePubSettings.use().onepubWebUrl]);
_colprint(['API endpoint:', OnePubSettings.use().onepubApiUrlAsString]);
}

void _printEnvironment() {
Expand Down Expand Up @@ -94,10 +92,11 @@ class DoctorCommand extends Command<int> {
Future<void> _status() async {
print('');
print(blue('Status'));
if (OnePubTokenStore().isLoggedIn) {
final settings = OnePubSettings.use();
if (OnePubTokenStore().isLoggedIn(settings.onepubApiUrl)) {
_colprint(['Logged In:', 'true']);
_colprint(['Active Member:', OnePubSettings.use.operatorEmail]);
_colprint(['Organisation:', OnePubSettings.use.organisationName]);
_colprint(['Active Member:', settings.operatorEmail]);
_colprint(['Organisation:', settings.organisationName]);
} else {
print(orange('''
You are not logged into OnePub.
Expand Down Expand Up @@ -137,7 +136,7 @@ void tokenStatus() {
print(blue('\nRepository tokens'));

final store = OnePubTokenStore();
if (!store.isLoggedIn) {
if (!store.isLoggedIn(OnePubSettings.use().onepubApiUrl)) {
print(red('No tokens found.'));
return;
}
Expand Down
Loading

0 comments on commit 7a34168

Please sign in to comment.