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 token;
|
||||||
String login;
|
String login;
|
||||||
String avatarUrl;
|
String avatarUrl;
|
||||||
int gitlabId;
|
int gitlabId; // For GitLab
|
||||||
|
String appPassword; // For Bitbucket
|
||||||
|
|
||||||
equals(Account a) {
|
// equals(Account a) {
|
||||||
final uri = Uri.parse(domain);
|
// final uri = Uri.parse(domain);
|
||||||
final uriA = Uri.parse(a.domain);
|
// final uriA = Uri.parse(a.domain);
|
||||||
|
|
||||||
// Treat domains as the same if they have the same hosts and ports
|
// // Treat domains as the same if they have the same hosts and ports
|
||||||
return a.platform == platform &&
|
// return a.platform == platform &&
|
||||||
a.login == login &&
|
// a.login == login &&
|
||||||
a.gitlabId == gitlabId &&
|
// a.gitlabId == gitlabId &&
|
||||||
uri.host == uriA.host &&
|
// uri.host == uriA.host &&
|
||||||
uri.port == uriA.port;
|
// uri.port == uriA.port;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Account({
|
Account({
|
||||||
@required this.platform,
|
@required this.platform,
|
||||||
@ -31,6 +32,7 @@ class Account {
|
|||||||
@required this.login,
|
@required this.login,
|
||||||
@required this.avatarUrl,
|
@required this.avatarUrl,
|
||||||
this.gitlabId,
|
this.gitlabId,
|
||||||
|
this.appPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Account.fromJson(Map<String, dynamic> json) =>
|
factory Account.fromJson(Map<String, dynamic> json) =>
|
||||||
|
@ -14,6 +14,7 @@ Account _$AccountFromJson(Map<String, dynamic> json) {
|
|||||||
login: json['login'] as String,
|
login: json['login'] as String,
|
||||||
avatarUrl: json['avatarUrl'] as String,
|
avatarUrl: json['avatarUrl'] as String,
|
||||||
gitlabId: json['gitlabId'] as int,
|
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('login', instance.login);
|
||||||
writeNotNull('avatarUrl', instance.avatarUrl);
|
writeNotNull('avatarUrl', instance.avatarUrl);
|
||||||
writeNotNull('gitlabId', instance.gitlabId);
|
writeNotNull('gitlabId', instance.gitlabId);
|
||||||
|
writeNotNull('appPassword', instance.appPassword);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:git_touch/models/bitbucket.dart';
|
||||||
import 'package:git_touch/models/gitea.dart';
|
import 'package:git_touch/models/gitea.dart';
|
||||||
import 'package:git_touch/utils/request_serilizer.dart';
|
import 'package:git_touch/utils/request_serilizer.dart';
|
||||||
import 'package:gql_http_link/gql_http_link.dart';
|
import 'package:gql_http_link/gql_http_link.dart';
|
||||||
@ -22,6 +23,7 @@ const clientId = 'df930d7d2e219f26142a';
|
|||||||
class PlatformType {
|
class PlatformType {
|
||||||
static const github = 'github';
|
static const github = 'github';
|
||||||
static const gitlab = 'gitlab';
|
static const gitlab = 'gitlab';
|
||||||
|
static const bitbucket = 'bitbucket';
|
||||||
static const gitea = 'gitea';
|
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 {
|
Future<void> init() async {
|
||||||
// Listen scheme
|
// Listen scheme
|
||||||
_sub = getUriLinksStream().listen(_onSchemeDetected, onError: (err) {
|
_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 _tokenController = TextEditingController();
|
||||||
final _domainController = TextEditingController();
|
final _domainController = TextEditingController();
|
||||||
|
|
||||||
|
// For Bitbucket
|
||||||
|
final _usernameController = TextEditingController();
|
||||||
|
final _passwordController = TextEditingController();
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
// initState() {
|
// initState() {
|
||||||
// super.initState();
|
// super.initState();
|
||||||
@ -114,15 +118,9 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
return Column(
|
return Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (showDomain)
|
if (showDomain)
|
||||||
MyTextField(
|
MyTextField(controller: _domainController, placeholder: 'Domain'),
|
||||||
controller: _domainController,
|
|
||||||
placeholder: 'Domain',
|
|
||||||
),
|
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
MyTextField(
|
MyTextField(placeholder: 'Access token', controller: _tokenController),
|
||||||
placeholder: 'Access token',
|
|
||||||
controller: _tokenController,
|
|
||||||
),
|
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
if (notes != null) ...notes,
|
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(
|
_buildAddItem(
|
||||||
text: 'Gitea Account',
|
text: 'Gitea Account',
|
||||||
brand: Octicons.git_branch, // TODO: brand icon
|
brand: Octicons.git_branch, // TODO: brand icon
|
||||||
|
Loading…
x
Reference in New Issue
Block a user