mirror of
https://github.com/git-touch/git-touch
synced 2025-03-20 13:10:04 +01:00
feat(bitbucket): app password login
This commit is contained in:
parent
79fe174b10
commit
53ecb3242f
@ -10,19 +10,20 @@ class Account {
|
||||
String token;
|
||||
String login;
|
||||
String avatarUrl;
|
||||
int gitlabId;
|
||||
int gitlabId; // For GitLab
|
||||
String appPassword; // For Bitbucket
|
||||
|
||||
equals(Account a) {
|
||||
final uri = Uri.parse(domain);
|
||||
final uriA = Uri.parse(a.domain);
|
||||
// equals(Account a) {
|
||||
// final uri = Uri.parse(domain);
|
||||
// final uriA = Uri.parse(a.domain);
|
||||
|
||||
// Treat domains as the same if they have the same hosts and ports
|
||||
return a.platform == platform &&
|
||||
a.login == login &&
|
||||
a.gitlabId == gitlabId &&
|
||||
uri.host == uriA.host &&
|
||||
uri.port == uriA.port;
|
||||
}
|
||||
// // Treat domains as the same if they have the same hosts and ports
|
||||
// return a.platform == platform &&
|
||||
// a.login == login &&
|
||||
// a.gitlabId == gitlabId &&
|
||||
// uri.host == uriA.host &&
|
||||
// uri.port == uriA.port;
|
||||
// }
|
||||
|
||||
Account({
|
||||
@required this.platform,
|
||||
@ -31,6 +32,7 @@ class Account {
|
||||
@required this.login,
|
||||
@required this.avatarUrl,
|
||||
this.gitlabId,
|
||||
this.appPassword,
|
||||
});
|
||||
|
||||
factory Account.fromJson(Map<String, dynamic> json) =>
|
||||
|
@ -14,6 +14,7 @@ Account _$AccountFromJson(Map<String, dynamic> json) {
|
||||
login: json['login'] as String,
|
||||
avatarUrl: json['avatarUrl'] as String,
|
||||
gitlabId: json['gitlabId'] as int,
|
||||
appPassword: json['appPassword'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
@ -32,5 +33,6 @@ Map<String, dynamic> _$AccountToJson(Account instance) {
|
||||
writeNotNull('login', instance.login);
|
||||
writeNotNull('avatarUrl', instance.avatarUrl);
|
||||
writeNotNull('gitlabId', instance.gitlabId);
|
||||
writeNotNull('appPassword', instance.appPassword);
|
||||
return val;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
import 'dart:convert';
|
||||
import 'dart:async';
|
||||
import 'package:git_touch/models/bitbucket.dart';
|
||||
import 'package:git_touch/models/gitea.dart';
|
||||
import 'package:git_touch/utils/request_serilizer.dart';
|
||||
import 'package:gql_http_link/gql_http_link.dart';
|
||||
@ -22,6 +23,7 @@ const clientId = 'df930d7d2e219f26142a';
|
||||
class PlatformType {
|
||||
static const github = 'github';
|
||||
static const gitlab = 'gitlab';
|
||||
static const bitbucket = 'bitbucket';
|
||||
static const gitea = 'gitea';
|
||||
}
|
||||
|
||||
@ -214,6 +216,32 @@ class AuthModel with ChangeNotifier {
|
||||
);
|
||||
}
|
||||
|
||||
Future loginToBb(String domain, String username, String appPassword) async {
|
||||
try {
|
||||
loading = true;
|
||||
notifyListeners();
|
||||
final uri = Uri.parse('$domain/api/2.0/user')
|
||||
.replace(userInfo: '$username:$appPassword');
|
||||
final res = await http.get(uri);
|
||||
if (res.statusCode >= 400) {
|
||||
throw 'status ${res.statusCode}';
|
||||
}
|
||||
final info = json.decode(res.body);
|
||||
final user = BbUser.fromJson(info);
|
||||
await _addAccount(Account(
|
||||
platform: PlatformType.bitbucket,
|
||||
domain: domain,
|
||||
token: user.username,
|
||||
login: username,
|
||||
avatarUrl: null,
|
||||
appPassword: appPassword,
|
||||
));
|
||||
} finally {
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> init() async {
|
||||
// Listen scheme
|
||||
_sub = getUriLinksStream().listen(_onSchemeDetected, onError: (err) {
|
||||
|
12
lib/models/bitbucket.dart
Normal file
12
lib/models/bitbucket.dart
Normal file
@ -0,0 +1,12 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
part 'bitbucket.g.dart';
|
||||
|
||||
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||
class BbUser {
|
||||
String username;
|
||||
String displayName;
|
||||
bool isStaff;
|
||||
DateTime createdOn;
|
||||
BbUser();
|
||||
factory BbUser.fromJson(Map<String, dynamic> json) => _$BbUserFromJson(json);
|
||||
}
|
24
lib/models/bitbucket.g.dart
Normal file
24
lib/models/bitbucket.g.dart
Normal file
@ -0,0 +1,24 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'bitbucket.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
BbUser _$BbUserFromJson(Map<String, dynamic> json) {
|
||||
return BbUser()
|
||||
..username = json['username'] as String
|
||||
..displayName = json['display_name'] as String
|
||||
..isStaff = json['is_staff'] as bool
|
||||
..createdOn = json['created_on'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_on'] as String);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$BbUserToJson(BbUser instance) => <String, dynamic>{
|
||||
'username': instance.username,
|
||||
'display_name': instance.displayName,
|
||||
'is_staff': instance.isStaff,
|
||||
'created_on': instance.createdOn?.toIso8601String(),
|
||||
};
|
@ -22,6 +22,10 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
final _tokenController = TextEditingController();
|
||||
final _domainController = TextEditingController();
|
||||
|
||||
// For Bitbucket
|
||||
final _usernameController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
|
||||
// @override
|
||||
// initState() {
|
||||
// super.initState();
|
||||
@ -114,15 +118,9 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
if (showDomain)
|
||||
MyTextField(
|
||||
controller: _domainController,
|
||||
placeholder: 'Domain',
|
||||
),
|
||||
MyTextField(controller: _domainController, placeholder: 'Domain'),
|
||||
SizedBox(height: 8),
|
||||
MyTextField(
|
||||
placeholder: 'Access token',
|
||||
controller: _tokenController,
|
||||
),
|
||||
MyTextField(placeholder: 'Access token', controller: _tokenController),
|
||||
SizedBox(height: 8),
|
||||
if (notes != null) ...notes,
|
||||
],
|
||||
@ -228,6 +226,43 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
}
|
||||
},
|
||||
),
|
||||
_buildAddItem(
|
||||
text: 'Bitbucket Account',
|
||||
brand: FontAwesome5Brands.bitbucket,
|
||||
onTap: () async {
|
||||
_domainController.text = 'https://bitbucket.org';
|
||||
final result = await theme.showConfirm(
|
||||
context,
|
||||
Column(
|
||||
children: <Widget>[
|
||||
MyTextField(
|
||||
controller: _domainController,
|
||||
placeholder: 'Domain'),
|
||||
SizedBox(height: 8),
|
||||
MyTextField(
|
||||
placeholder: 'Username',
|
||||
controller: _usernameController),
|
||||
SizedBox(height: 8),
|
||||
MyTextField(
|
||||
placeholder: 'App password',
|
||||
controller: _passwordController),
|
||||
SizedBox(height: 8),
|
||||
// TODO: permissions
|
||||
],
|
||||
),
|
||||
);
|
||||
if (result == true) {
|
||||
try {
|
||||
await auth.loginToBb(
|
||||
_domainController.text,
|
||||
_usernameController.text,
|
||||
_passwordController.text);
|
||||
} catch (err) {
|
||||
showError(err);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
_buildAddItem(
|
||||
text: 'Gitea Account',
|
||||
brand: Octicons.git_branch, // TODO: brand icon
|
||||
|
Loading…
x
Reference in New Issue
Block a user