Rename, GraphQL Flutter Cookie Basics, & GraphQL Flutter Model Gen

This commit is contained in:
2021-02-10 00:09:57 -05:00
parent a2d0432147
commit f0aee561ad
41 changed files with 1461 additions and 258 deletions

View File

@@ -1,19 +1,25 @@
import 'dart:io';
import 'dart:async';
import 'dart:convert';
import 'package:meta/meta.dart';
import 'package:http/http.dart' as http;
// ignore: uri_does_not_exist
import 'cookie_client_stub.dart'
// ignore: uri_does_not_exist
if (dart.library.html) 'browser_cookie_client.dart'
// ignore: uri_does_not_exist
if (dart.library.io) 'io_cookie_client.dart';
import 'package:imagini/models/api/response/LoginResponse.dart';
import 'package:meta/meta.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:imagini/models/api/response/login_response.dart';
class APIProvider{
String _server, _accessToken, _refreshToken;
static const String _LOGIN_API = "/api/v1/Login";
static const String _MEDIA_ITEMS_API = "/api/v1/MediaItems";
static const String _ALBUMS_API = "/api/v1/Albums";
static const String _TAGS_API = "/api/v1/Tags";
GraphQLClient _client;
HttpLink httpLink;
// CookieLink cookieLink;
static const String _GRAPHQL_ENDPOINT = "/query";
APIProvider({
@required String server,
@@ -23,9 +29,27 @@ class APIProvider{
_server = server;
_accessToken = accessToken;
_refreshToken = refreshToken;
httpLink = HttpLink(_server + _GRAPHQL_ENDPOINT,
httpClient: getCookieClient(),
);
// cookieLink = CookieLink(_updateAccessToken, _updateRefreshToken);
_client = GraphQLClient(
cache: GraphQLCache(),
link: httpLink,
);
}
// Endpoint: /api/v1/Login
// void _updateAccessToken(_accessToken) {
// print("Updating Access Token: $_accessToken");
// this._accessToken = _accessToken;
// }
// void _updateRefreshToken(_refreshToken) {
// print("Updating Refresh Token: $_accessToken");
// this._refreshToken = _refreshToken;
// }
Future<LoginResponse> login([
String username,
String password,
@@ -34,37 +58,28 @@ class APIProvider{
(username != null && password != null) ||
(_accessToken != null && _refreshToken != null)
);
String loginQuery = """
query login(\$user: String!, \$password: String!, \$deviceID: ID) {
login(user: \$user, password: \$password, deviceID: \$deviceID) {
result,
device {
id
}
}
}""";
http.Response response = await http.post(
Uri.encodeFull(_server + _LOGIN_API),
body: jsonEncode(<String, String>{
'user': username,
'password': password,
}),
).timeout(Duration(seconds: 10));
if (response.statusCode != 200) {
// Fuck
return LoginResponse.fromJson(jsonDecode(response.body));
}
QueryResult response = await _client.query(
QueryOptions(
document: gql(loginQuery),
variables: {
"user": "admin",
"password": "admin"
},
)
);
// Success
String setCookieVal = response.headers["set-cookie"];
List<Cookie> allCookies = setCookieVal.split(',')
.map((cookie) => Cookie.fromSetCookieValue(cookie)).toList();
Cookie accessToken = allCookies.firstWhere((cookie) => cookie.name == "AccessToken");
Cookie refreshToken = allCookies.firstWhere((cookie) => cookie.name == "RefreshToken");
_accessToken = accessToken.toString();
_refreshToken = refreshToken.toString();
print("Status: ${response.statusCode.toString()}");
print("Body: ${response.body.toString()}");
print("AccessToken: ${accessToken.toString()}");
print("RefreshToken: ${refreshToken.toString()}");
return LoginResponse.fromJson(jsonDecode(response.body));
return LoginResponse.fromJson(jsonDecode("{}"));
}
void logout() {

View File

@@ -0,0 +1,30 @@
import 'package:http/browser_client.dart';
import "package:http/http.dart";
BaseClient getCookieClient() => ClientWithCookies();
class ClientWithCookies extends BrowserClient {
String _accessToken = "asdasdasd";
String _refreshToken;
@override
Future<StreamedResponse> send(BaseRequest request) async {
request.headers.addAll({
'X-Imagini-AccessToken': _accessToken,
'X-Imagini-RefreshToken': _refreshToken,
});
return super.send(request).then((response) {
if (response.headers.containsKey("x-imagini-accesstoken")) {
this._accessToken = response.headers["x-imagini-accesstoken"];
}
if (response.headers.containsKey("x-imagini-refreshtoken")) {
this._refreshToken = response.headers["x-imagini-refreshtoken"];
}
print("Access Token: $_accessToken");
print("Refresh Token: $_refreshToken");
return response;
});
}
}

View File

@@ -0,0 +1,4 @@
import 'package:http/http.dart';
BaseClient getCookieClient() => throw UnsupportedError(
'Cannot create a client without dart:html or dart:io.');

View File

@@ -1,5 +1,5 @@
import 'package:imagini/api/APIProvider.dart';
import 'package:imagini/models/api/response/LoginResponse.dart';
import 'package:imagini/api/api_provider.dart';
import 'package:imagini/models/api/response/login_response.dart';
class ImaginiAPIRepository {
APIProvider _apiProvider;

View File

@@ -0,0 +1,28 @@
import 'package:http/io_client.dart';
import "package:http/http.dart";
BaseClient getCookieClient() => IOClientWithCookies();
class IOClientWithCookies extends IOClient {
String _accessToken;
String _refreshToken;
@override
Future<IOStreamedResponse> send(BaseRequest request) async {
// String cookie = await getCookie();
// String getCookieString(String _) => cookie;
// request.headers.update('cookie', getCookieString);
return super.send(request).then((response) {
if (response.headers.containsKey("x-imagini-accesstoken")) {
this._accessToken = response.headers["x-imagini-accesstoken"];
}
if (response.headers.containsKey("x-imagini-refreshtoken")) {
this._refreshToken = response.headers["x-imagini-refreshtoken"];
}
print("Access Token: $_accessToken");
print("Refresh Token: $_refreshToken");
return response;
});
}
}

View File

@@ -1,9 +1,9 @@
import 'dart:async';
import 'package:imagini/core/ImaginiApplication.dart';
import 'package:imagini/api/ImaginiAPIRepository.dart';
import 'package:imagini/core/imagini_application.dart';
import 'package:imagini/api/imagini_api_repository.dart';
import 'package:imagini/models/api/response/LoginResponse.dart';
import 'package:imagini/models/api/response/login_response.dart';
class SplashBloc{

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:imagini/core/AppComponent.dart';
import 'package:imagini/core/ImaginiApplication.dart';
import 'package:imagini/core/app_component.dart';
import 'package:imagini/core/imagini_application.dart';
class Env {
static Env value;

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:imagini/core/Env.dart';
import 'package:imagini/core/AppProvider.dart';
import 'package:imagini/core/ImaginiApplication.dart';
import 'package:imagini/core/env.dart';
import 'package:imagini/core/app_provider.dart';
import 'package:imagini/core/imagini_application.dart';
class AppComponent extends StatefulWidget {

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';
import 'package:imagini/core/ImaginiApplication.dart';
import 'package:imagini/core/imagini_application.dart';
class AppProvider extends InheritedWidget {

View File

@@ -1,9 +1,9 @@
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:imagini/screens/HomeScreen.dart';
import 'package:imagini/screens/LoginScreen.dart';
import 'package:imagini/screens/SplashScreen.dart';
import 'package:imagini/screens/home_screen.dart';
import 'package:imagini/screens/login_screen.dart';
import 'package:imagini/screens/splash_screen.dart';
var splashHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {

View File

@@ -1,8 +1,8 @@
import 'package:fluro/fluro.dart';
import 'package:imagini/core/AppRoutes.dart';
import 'package:imagini/api/APIProvider.dart';
import 'package:imagini/api/ImaginiAPIRepository.dart';
import 'package:imagini/core/app_routes.dart';
import 'package:imagini/api/api_provider.dart';
import 'package:imagini/api/imagini_api_repository.dart';
class ImaginiApplication {
FluroRouter router;
@@ -21,7 +21,7 @@ class ImaginiApplication {
}
_initAPIRepository() {
APIProvider apiProvider = new APIProvider(server: "http://10.0.20.170:8484");
APIProvider apiProvider = new APIProvider(server: "http://localhost:8484");
imaginiAPI = ImaginiAPIRepository(apiProvider);
}
}

View File

@@ -0,0 +1,2 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
export 'imgagini_graphql.graphql.dart';

View File

@@ -0,0 +1,354 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
import 'package:meta/meta.dart';
import 'package:artemis/artemis.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:equatable/equatable.dart';
import 'package:gql/ast.dart';
import 'package:http/http.dart';
import 'package:imagini/helpers/upload_serializer.dart';
part 'imgagini_graphql.graphql.g.dart';
@JsonSerializable(explicitToJson: true)
class Login$Query$AuthResponse$Device with EquatableMixin {
Login$Query$AuthResponse$Device();
factory Login$Query$AuthResponse$Device.fromJson(Map<String, dynamic> json) =>
_$Login$Query$AuthResponse$DeviceFromJson(json);
String id;
@override
List<Object> get props => [id];
Map<String, dynamic> toJson() =>
_$Login$Query$AuthResponse$DeviceToJson(this);
}
@JsonSerializable(explicitToJson: true)
class Login$Query$AuthResponse with EquatableMixin {
Login$Query$AuthResponse();
factory Login$Query$AuthResponse.fromJson(Map<String, dynamic> json) =>
_$Login$Query$AuthResponseFromJson(json);
@JsonKey(unknownEnumValue: AuthResult.artemisUnknown)
AuthResult result;
Login$Query$AuthResponse$Device device;
@override
List<Object> get props => [result, device];
Map<String, dynamic> toJson() => _$Login$Query$AuthResponseToJson(this);
}
@JsonSerializable(explicitToJson: true)
class Login$Query with EquatableMixin {
Login$Query();
factory Login$Query.fromJson(Map<String, dynamic> json) =>
_$Login$QueryFromJson(json);
Login$Query$AuthResponse login;
@override
List<Object> get props => [login];
Map<String, dynamic> toJson() => _$Login$QueryToJson(this);
}
@JsonSerializable(explicitToJson: true)
class CreateMediaItem$Mutation$MediaItem with EquatableMixin {
CreateMediaItem$Mutation$MediaItem();
factory CreateMediaItem$Mutation$MediaItem.fromJson(
Map<String, dynamic> json) =>
_$CreateMediaItem$Mutation$MediaItemFromJson(json);
String id;
DateTime createdAt;
DateTime updatedAt;
DateTime exifDate;
double latitude;
double longitude;
bool isVideo;
String fileName;
String origName;
String userID;
@override
List<Object> get props => [
id,
createdAt,
updatedAt,
exifDate,
latitude,
longitude,
isVideo,
fileName,
origName,
userID
];
Map<String, dynamic> toJson() =>
_$CreateMediaItem$Mutation$MediaItemToJson(this);
}
@JsonSerializable(explicitToJson: true)
class CreateMediaItem$Mutation with EquatableMixin {
CreateMediaItem$Mutation();
factory CreateMediaItem$Mutation.fromJson(Map<String, dynamic> json) =>
_$CreateMediaItem$MutationFromJson(json);
CreateMediaItem$Mutation$MediaItem createMediaItem;
@override
List<Object> get props => [createMediaItem];
Map<String, dynamic> toJson() => _$CreateMediaItem$MutationToJson(this);
}
enum AuthResult {
@JsonValue('Success')
success,
@JsonValue('Failure')
failure,
@JsonValue('ARTEMIS_UNKNOWN')
artemisUnknown,
}
@JsonSerializable(explicitToJson: true)
class LoginArguments extends JsonSerializable with EquatableMixin {
LoginArguments({@required this.user, @required this.password, this.deviceID});
@override
factory LoginArguments.fromJson(Map<String, dynamic> json) =>
_$LoginArgumentsFromJson(json);
final String user;
final String password;
final String deviceID;
@override
List<Object> get props => [user, password, deviceID];
@override
Map<String, dynamic> toJson() => _$LoginArgumentsToJson(this);
}
class LoginQuery extends GraphQLQuery<Login$Query, LoginArguments> {
LoginQuery({this.variables});
@override
final DocumentNode document = DocumentNode(definitions: [
OperationDefinitionNode(
type: OperationType.query,
name: NameNode(value: 'login'),
variableDefinitions: [
VariableDefinitionNode(
variable: VariableNode(name: NameNode(value: 'user')),
type: NamedTypeNode(
name: NameNode(value: 'String'), isNonNull: true),
defaultValue: DefaultValueNode(value: null),
directives: []),
VariableDefinitionNode(
variable: VariableNode(name: NameNode(value: 'password')),
type: NamedTypeNode(
name: NameNode(value: 'String'), isNonNull: true),
defaultValue: DefaultValueNode(value: null),
directives: []),
VariableDefinitionNode(
variable: VariableNode(name: NameNode(value: 'deviceID')),
type:
NamedTypeNode(name: NameNode(value: 'ID'), isNonNull: false),
defaultValue: DefaultValueNode(value: null),
directives: [])
],
directives: [],
selectionSet: SelectionSetNode(selections: [
FieldNode(
name: NameNode(value: 'login'),
alias: null,
arguments: [
ArgumentNode(
name: NameNode(value: 'user'),
value: VariableNode(name: NameNode(value: 'user'))),
ArgumentNode(
name: NameNode(value: 'password'),
value: VariableNode(name: NameNode(value: 'password'))),
ArgumentNode(
name: NameNode(value: 'deviceID'),
value: VariableNode(name: NameNode(value: 'deviceID')))
],
directives: [],
selectionSet: SelectionSetNode(selections: [
FieldNode(
name: NameNode(value: 'result'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'device'),
alias: null,
arguments: [],
directives: [],
selectionSet: SelectionSetNode(selections: [
FieldNode(
name: NameNode(value: 'id'),
alias: null,
arguments: [],
directives: [],
selectionSet: null)
]))
]))
]))
]);
@override
final String operationName = 'login';
@override
final LoginArguments variables;
@override
List<Object> get props => [document, operationName, variables];
@override
Login$Query parse(Map<String, dynamic> json) => Login$Query.fromJson(json);
}
@JsonSerializable(explicitToJson: true)
class CreateMediaItemArguments extends JsonSerializable with EquatableMixin {
CreateMediaItemArguments({@required this.file});
@override
factory CreateMediaItemArguments.fromJson(Map<String, dynamic> json) =>
_$CreateMediaItemArgumentsFromJson(json);
@JsonKey(
fromJson: fromGraphQLUploadToDartMultipartFile,
toJson: fromDartMultipartFileToGraphQLUpload)
final MultipartFile file;
@override
List<Object> get props => [file];
@override
Map<String, dynamic> toJson() => _$CreateMediaItemArgumentsToJson(this);
}
class CreateMediaItemMutation
extends GraphQLQuery<CreateMediaItem$Mutation, CreateMediaItemArguments> {
CreateMediaItemMutation({this.variables});
@override
final DocumentNode document = DocumentNode(definitions: [
OperationDefinitionNode(
type: OperationType.mutation,
name: NameNode(value: 'createMediaItem'),
variableDefinitions: [
VariableDefinitionNode(
variable: VariableNode(name: NameNode(value: 'file')),
type: NamedTypeNode(
name: NameNode(value: 'Upload'), isNonNull: true),
defaultValue: DefaultValueNode(value: null),
directives: [])
],
directives: [],
selectionSet: SelectionSetNode(selections: [
FieldNode(
name: NameNode(value: 'createMediaItem'),
alias: null,
arguments: [
ArgumentNode(
name: NameNode(value: 'input'),
value: ObjectValueNode(fields: [
ObjectFieldNode(
name: NameNode(value: 'file'),
value: VariableNode(name: NameNode(value: 'file')))
]))
],
directives: [],
selectionSet: SelectionSetNode(selections: [
FieldNode(
name: NameNode(value: 'id'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'createdAt'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'updatedAt'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'exifDate'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'latitude'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'longitude'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'isVideo'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'fileName'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'origName'),
alias: null,
arguments: [],
directives: [],
selectionSet: null),
FieldNode(
name: NameNode(value: 'userID'),
alias: null,
arguments: [],
directives: [],
selectionSet: null)
]))
]))
]);
@override
final String operationName = 'createMediaItem';
@override
final CreateMediaItemArguments variables;
@override
List<Object> get props => [document, operationName, variables];
@override
CreateMediaItem$Mutation parse(Map<String, dynamic> json) =>
CreateMediaItem$Mutation.fromJson(json);
}

View File

@@ -0,0 +1,166 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'imgagini_graphql.graphql.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Login$Query$AuthResponse$Device _$Login$Query$AuthResponse$DeviceFromJson(
Map<String, dynamic> json) {
return Login$Query$AuthResponse$Device()..id = json['id'] as String;
}
Map<String, dynamic> _$Login$Query$AuthResponse$DeviceToJson(
Login$Query$AuthResponse$Device instance) =>
<String, dynamic>{
'id': instance.id,
};
Login$Query$AuthResponse _$Login$Query$AuthResponseFromJson(
Map<String, dynamic> json) {
return Login$Query$AuthResponse()
..result = _$enumDecodeNullable(_$AuthResultEnumMap, json['result'],
unknownValue: AuthResult.artemisUnknown)
..device = json['device'] == null
? null
: Login$Query$AuthResponse$Device.fromJson(
json['device'] as Map<String, dynamic>);
}
Map<String, dynamic> _$Login$Query$AuthResponseToJson(
Login$Query$AuthResponse instance) =>
<String, dynamic>{
'result': _$AuthResultEnumMap[instance.result],
'device': instance.device?.toJson(),
};
T _$enumDecode<T>(
Map<T, dynamic> enumValues,
dynamic source, {
T unknownValue,
}) {
if (source == null) {
throw ArgumentError('A value must be provided. Supported values: '
'${enumValues.values.join(', ')}');
}
final value = enumValues.entries
.singleWhere((e) => e.value == source, orElse: () => null)
?.key;
if (value == null && unknownValue == null) {
throw ArgumentError('`$source` is not one of the supported values: '
'${enumValues.values.join(', ')}');
}
return value ?? unknownValue;
}
T _$enumDecodeNullable<T>(
Map<T, dynamic> enumValues,
dynamic source, {
T unknownValue,
}) {
if (source == null) {
return null;
}
return _$enumDecode<T>(enumValues, source, unknownValue: unknownValue);
}
const _$AuthResultEnumMap = {
AuthResult.success: 'Success',
AuthResult.failure: 'Failure',
AuthResult.artemisUnknown: 'ARTEMIS_UNKNOWN',
};
Login$Query _$Login$QueryFromJson(Map<String, dynamic> json) {
return Login$Query()
..login = json['login'] == null
? null
: Login$Query$AuthResponse.fromJson(
json['login'] as Map<String, dynamic>);
}
Map<String, dynamic> _$Login$QueryToJson(Login$Query instance) =>
<String, dynamic>{
'login': instance.login?.toJson(),
};
CreateMediaItem$Mutation$MediaItem _$CreateMediaItem$Mutation$MediaItemFromJson(
Map<String, dynamic> json) {
return CreateMediaItem$Mutation$MediaItem()
..id = json['id'] as String
..createdAt = json['createdAt'] == null
? null
: DateTime.parse(json['createdAt'] as String)
..updatedAt = json['updatedAt'] == null
? null
: DateTime.parse(json['updatedAt'] as String)
..exifDate = json['exifDate'] == null
? null
: DateTime.parse(json['exifDate'] as String)
..latitude = (json['latitude'] as num)?.toDouble()
..longitude = (json['longitude'] as num)?.toDouble()
..isVideo = json['isVideo'] as bool
..fileName = json['fileName'] as String
..origName = json['origName'] as String
..userID = json['userID'] as String;
}
Map<String, dynamic> _$CreateMediaItem$Mutation$MediaItemToJson(
CreateMediaItem$Mutation$MediaItem instance) =>
<String, dynamic>{
'id': instance.id,
'createdAt': instance.createdAt?.toIso8601String(),
'updatedAt': instance.updatedAt?.toIso8601String(),
'exifDate': instance.exifDate?.toIso8601String(),
'latitude': instance.latitude,
'longitude': instance.longitude,
'isVideo': instance.isVideo,
'fileName': instance.fileName,
'origName': instance.origName,
'userID': instance.userID,
};
CreateMediaItem$Mutation _$CreateMediaItem$MutationFromJson(
Map<String, dynamic> json) {
return CreateMediaItem$Mutation()
..createMediaItem = json['createMediaItem'] == null
? null
: CreateMediaItem$Mutation$MediaItem.fromJson(
json['createMediaItem'] as Map<String, dynamic>);
}
Map<String, dynamic> _$CreateMediaItem$MutationToJson(
CreateMediaItem$Mutation instance) =>
<String, dynamic>{
'createMediaItem': instance.createMediaItem?.toJson(),
};
LoginArguments _$LoginArgumentsFromJson(Map<String, dynamic> json) {
return LoginArguments(
user: json['user'] as String,
password: json['password'] as String,
deviceID: json['deviceID'] as String,
);
}
Map<String, dynamic> _$LoginArgumentsToJson(LoginArguments instance) =>
<String, dynamic>{
'user': instance.user,
'password': instance.password,
'deviceID': instance.deviceID,
};
CreateMediaItemArguments _$CreateMediaItemArgumentsFromJson(
Map<String, dynamic> json) {
return CreateMediaItemArguments(
file: fromGraphQLUploadToDartMultipartFile(json['file'] as MultipartFile),
);
}
Map<String, dynamic> _$CreateMediaItemArgumentsToJson(
CreateMediaItemArguments instance) =>
<String, dynamic>{
'file': fromDartMultipartFileToGraphQLUpload(instance.file),
};

View File

@@ -0,0 +1,4 @@
import 'package:http/http.dart';
MultipartFile fromGraphQLUploadToDartMultipartFile(MultipartFile file) => file;
MultipartFile fromDartMultipartFileToGraphQLUpload(MultipartFile file) => file;

View File

@@ -1,4 +1,4 @@
import 'package:imagini/core/Env.dart';
import 'package:imagini/core/env.dart';
void main() => ProductionImagini();