mirror of
https://github.com/johrpan/musicus_mobile.git
synced 2025-10-26 18:57:25 +01:00
client: Update account API
This commit is contained in:
parent
0847dde610
commit
ea1469c0dd
1 changed files with 139 additions and 41 deletions
|
|
@ -5,28 +5,28 @@ import 'package:http/http.dart' as http;
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:musicus_database/musicus_database.dart';
|
import 'package:musicus_database/musicus_database.dart';
|
||||||
|
|
||||||
/// A user of the Musicus API.
|
/// Credentials for a Musicus account.
|
||||||
class User {
|
class MusicusAccountCredentials {
|
||||||
/// Username.
|
/// The user's username.
|
||||||
final String name;
|
final String username;
|
||||||
|
|
||||||
/// An optional email address.
|
|
||||||
final String email;
|
|
||||||
|
|
||||||
/// The user's password.
|
/// The user's password.
|
||||||
final String password;
|
final String password;
|
||||||
|
|
||||||
User({
|
MusicusAccountCredentials({
|
||||||
this.name,
|
this.username,
|
||||||
this.email,
|
|
||||||
this.password,
|
this.password,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
/// Additional information on a Musicus account.
|
||||||
'name': name,
|
class MusicusAccountDetails {
|
||||||
'email': email,
|
/// An optional email address.
|
||||||
'password': password,
|
final String email;
|
||||||
};
|
|
||||||
|
MusicusAccountDetails({
|
||||||
|
this.email,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple http client for the Musicus server.
|
/// A simple http client for the Musicus server.
|
||||||
|
|
@ -47,18 +47,22 @@ class MusicusClient {
|
||||||
/// Base path to the root location of the Musicus API.
|
/// Base path to the root location of the Musicus API.
|
||||||
final String basePath;
|
final String basePath;
|
||||||
|
|
||||||
User _user;
|
MusicusAccountCredentials _credentials;
|
||||||
|
|
||||||
/// The user to login.
|
/// Account credentials for login.
|
||||||
User get user => _user;
|
///
|
||||||
set user(User user) {
|
/// If this is null, unauthorized requests will fail.
|
||||||
_user = user;
|
MusicusAccountCredentials get credentials => _credentials;
|
||||||
|
set credentials(MusicusAccountCredentials credentials) {
|
||||||
|
_credentials = credentials;
|
||||||
_token = null;
|
_token = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final _client = http.Client();
|
final _client = http.Client();
|
||||||
|
|
||||||
/// The last retrieved access token.
|
/// The last retrieved access token.
|
||||||
|
///
|
||||||
|
/// If this is null, a new token should be retrieved using [login] if needed.
|
||||||
String _token;
|
String _token;
|
||||||
|
|
||||||
MusicusClient({
|
MusicusClient({
|
||||||
|
|
@ -66,11 +70,11 @@ class MusicusClient {
|
||||||
@required this.host,
|
@required this.host,
|
||||||
this.port = 443,
|
this.port = 443,
|
||||||
this.basePath,
|
this.basePath,
|
||||||
User user,
|
MusicusAccountCredentials credentials,
|
||||||
}) : assert(scheme != null),
|
}) : assert(scheme != null),
|
||||||
assert(port != null),
|
assert(port != null),
|
||||||
assert(host != null),
|
assert(host != null),
|
||||||
_user = user;
|
_credentials = credentials;
|
||||||
|
|
||||||
/// Create an URI using member variables and parameters.
|
/// Create an URI using member variables and parameters.
|
||||||
Uri createUri({
|
Uri createUri({
|
||||||
|
|
@ -86,39 +90,126 @@ class MusicusClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a new user.
|
/// Create a new Musicus account.
|
||||||
///
|
///
|
||||||
/// This will return true, if the action was successful. Subsequent requests
|
/// The email address is optional. This will return true, if the action was
|
||||||
/// will automatically be made as the new user.
|
/// successful. In that case, the new credentials will automatically be
|
||||||
Future<bool> register(User newUser) async {
|
/// stored as under [credentials] and used for subsequent requests.
|
||||||
|
Future<bool> registerAccount({
|
||||||
|
@required String username,
|
||||||
|
@required String password,
|
||||||
|
String email,
|
||||||
|
}) async {
|
||||||
final response = await _client.post(
|
final response = await _client.post(
|
||||||
createUri(
|
createUri(
|
||||||
path: '/register',
|
path: '/account/register',
|
||||||
),
|
),
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
body: jsonEncode(newUser.toJson()),
|
body: jsonEncode({
|
||||||
|
'username': username,
|
||||||
|
'password': password,
|
||||||
|
'email': email,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == HttpStatus.ok) {
|
if (response.statusCode == HttpStatus.ok) {
|
||||||
_user = newUser;
|
_credentials = MusicusAccountCredentials(
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
|
|
||||||
_token = null;
|
_token = null;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve an access token for [user].
|
/// Get the current account details.
|
||||||
|
Future<MusicusAccountDetails> getAccountDetails() async {
|
||||||
|
assert(_credentials != null);
|
||||||
|
|
||||||
|
final response = await _authorized(
|
||||||
|
'GET',
|
||||||
|
createUri(path: '/account/details'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == HttpStatus.ok) {
|
||||||
|
final json = jsonDecode(response.body);
|
||||||
|
|
||||||
|
return MusicusAccountDetails(
|
||||||
|
email: json['email'],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Change the account details for the currently used user account.
|
||||||
///
|
///
|
||||||
/// The token will land in [_token]. If the login failed, a
|
/// This will throw a [MusicusLoginFailedException] if the account doesn't
|
||||||
/// [MusicusLoginFailedException] will be thrown.
|
/// exist or the old password was wrong.
|
||||||
Future<void> _login() async {
|
Future<void> updateAccount(String newEmail, String newPassword) async {
|
||||||
|
assert(_credentials != null);
|
||||||
|
|
||||||
|
final response = await _client.post(
|
||||||
|
createUri(path: '/account/details'),
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: jsonEncode({
|
||||||
|
'username': _credentials.username,
|
||||||
|
'password': _credentials.password,
|
||||||
|
'newEmail': newEmail,
|
||||||
|
'newPassword': newPassword,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
|
throw MusicusLoginFailedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete the currently used Musicus account.
|
||||||
|
///
|
||||||
|
/// This will throw a [MusicusLoginFailedException] if the user doesn't exist
|
||||||
|
/// or the password was wrong.
|
||||||
|
Future<void> deleteAccount() async {
|
||||||
|
assert(_credentials != null);
|
||||||
|
|
||||||
|
final response = await _client.post(
|
||||||
|
createUri(path: '/account/delete'),
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: jsonEncode({
|
||||||
|
'username': _credentials.username,
|
||||||
|
'password': _credentials.password,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == HttpStatus.ok) {
|
||||||
|
_credentials = null;
|
||||||
|
_token = null;
|
||||||
|
} else {
|
||||||
|
throw MusicusLoginFailedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve an access token for the current user.
|
||||||
|
///
|
||||||
|
/// This will be called automatically, when the client calls a method that
|
||||||
|
/// requires it. If the login failed, a [MusicusLoginFailedException] will be
|
||||||
|
/// thrown.
|
||||||
|
Future<void> login() async {
|
||||||
|
assert(_credentials != null);
|
||||||
|
|
||||||
final response = await _client.post(
|
final response = await _client.post(
|
||||||
createUri(
|
createUri(
|
||||||
path: '/login',
|
path: '/account/login',
|
||||||
),
|
),
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
body: jsonEncode(user.toJson()),
|
body: jsonEncode({
|
||||||
|
'username': _credentials.username,
|
||||||
|
'password': _credentials.password,
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == HttpStatus.ok) {
|
if (response.statusCode == HttpStatus.ok) {
|
||||||
|
|
@ -138,12 +229,19 @@ class MusicusClient {
|
||||||
/// a [MusicusNotAuthorizedException].
|
/// a [MusicusNotAuthorizedException].
|
||||||
Future<http.Response> _authorized(String method, Uri uri,
|
Future<http.Response> _authorized(String method, Uri uri,
|
||||||
{Map<String, String> headers, String body}) async {
|
{Map<String, String> headers, String body}) async {
|
||||||
if (_user != null) {
|
if (_credentials != null) {
|
||||||
Future<http.Response> _request() async {
|
Future<http.Response> _request() async {
|
||||||
final request = http.Request(method, uri);
|
final request = http.Request(method, uri);
|
||||||
request.headers.addAll(headers);
|
|
||||||
|
if (headers != null) {
|
||||||
|
request.headers.addAll(headers);
|
||||||
|
}
|
||||||
|
|
||||||
request.headers['Authorization'] = 'Bearer $_token';
|
request.headers['Authorization'] = 'Bearer $_token';
|
||||||
request.body = body;
|
|
||||||
|
if (body != null) {
|
||||||
|
request.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
return await http.Response.fromStream(await _client.send(request));
|
return await http.Response.fromStream(await _client.send(request));
|
||||||
}
|
}
|
||||||
|
|
@ -153,11 +251,11 @@ class MusicusClient {
|
||||||
if (_token != null) {
|
if (_token != null) {
|
||||||
response = await _request();
|
response = await _request();
|
||||||
if (response.statusCode == HttpStatus.unauthorized) {
|
if (response.statusCode == HttpStatus.unauthorized) {
|
||||||
await _login();
|
await login();
|
||||||
response = await _request();
|
response = await _request();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await _login();
|
await login();
|
||||||
response = await _request();
|
response = await _request();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue