Line data Source code
1 : // ignore_for_file: constant_identifier_names
2 :
3 : /* MIT License
4 : *
5 : * Copyright (C) 2019, 2020, 2021 Famedly GmbH
6 : *
7 : * Permission is hereby granted, free of charge, to any person obtaining a copy
8 : * of this software and associated documentation files (the "Software"), to deal
9 : * in the Software without restriction, including without limitation the rights
10 : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 : * copies of the Software, and to permit persons to whom the Software is
12 : * furnished to do so, subject to the following conditions:
13 : *
14 : * The above copyright notice and this permission notice shall be included in all
15 : * copies or substantial portions of the Software.
16 : *
17 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 : * SOFTWARE.
24 : */
25 :
26 : import 'dart:convert';
27 :
28 : import 'package:http/http.dart' as http;
29 :
30 : import 'package:matrix/matrix_api_lite.dart';
31 :
32 : enum MatrixError {
33 : M_UNKNOWN,
34 : M_UNKNOWN_TOKEN,
35 : M_NOT_FOUND,
36 : M_FORBIDDEN,
37 : M_LIMIT_EXCEEDED,
38 : M_USER_IN_USE,
39 : M_THREEPID_IN_USE,
40 : M_THREEPID_DENIED,
41 : M_THREEPID_NOT_FOUND,
42 : M_THREEPID_AUTH_FAILED,
43 : M_TOO_LARGE,
44 : M_MISSING_PARAM,
45 : M_UNSUPPORTED_ROOM_VERSION,
46 : M_UNRECOGNIZED,
47 : M_BAD_JSON,
48 : M_NOT_JSON,
49 : M_UNAUTHORIZED,
50 : M_USER_DEACTIVATED,
51 : M_INVALID_USERNAME,
52 : M_ROOM_IN_USE,
53 : M_INVALID_ROOM_STATE,
54 : M_SERVER_NOT_TRUSTED,
55 : M_INCOMPATIBLE_ROOM_VERSION,
56 : M_BAD_STATE,
57 : M_GUEST_ACCESS_FORBIDDEN,
58 : M_CAPTCHA_NEEDED,
59 : M_CAPTCHA_INVALID,
60 : M_INVALID_PARAM,
61 : M_EXCLUSIVE,
62 : M_RESOURCE_LIMIT_EXCEEDED,
63 : M_CANNOT_LEAVE_SERVER_NOTICE_ROOM,
64 : }
65 :
66 : /// Represents a special response from the Homeserver for errors.
67 : class MatrixException implements Exception {
68 : final Map<String, Object?> raw;
69 :
70 : /// The unique identifier for this error.
71 5 : String get errcode =>
72 10 : raw.tryGet<String>('errcode') ??
73 2 : (requireAdditionalAuthentication ? 'M_FORBIDDEN' : 'M_UNKNOWN');
74 :
75 : /// A human readable error description.
76 1 : String get errorMessage =>
77 2 : raw.tryGet<String>('error') ??
78 0 : (requireAdditionalAuthentication
79 : ? 'Require additional authentication'
80 : : 'Unknown error');
81 :
82 : /// The frozen request which triggered this Error
83 : http.Response? response;
84 :
85 2 : MatrixException(http.Response this.response)
86 4 : : raw = json.decode(response.body) as Map<String, Object?>;
87 :
88 7 : MatrixException.fromJson(Map<String, Object?> content) : raw = content;
89 :
90 1 : @override
91 3 : String toString() => '$errcode: $errorMessage';
92 :
93 : /// Returns the errcode as an [MatrixError].
94 6 : MatrixError get error => MatrixError.values.firstWhere(
95 12 : (e) => e.name == errcode,
96 2 : orElse: () => MatrixError.M_UNKNOWN,
97 : );
98 :
99 12 : int? get retryAfterMs => raw.tryGet<int>('retry_after_ms');
100 :
101 : /// This is a session identifier that the client must pass back to the homeserver, if one is provided,
102 : /// in subsequent attempts to authenticate in the same API call.
103 12 : String? get session => raw.tryGet<String>('session');
104 :
105 : /// Returns true if the server requires additional authentication.
106 4 : bool get requireAdditionalAuthentication => response != null
107 6 : ? response!.statusCode == 401
108 0 : : authenticationFlows != null;
109 :
110 : /// For each endpoint, a server offers one or more 'flows' that the client can use
111 : /// to authenticate itself. Each flow comprises a series of stages. If this request
112 : /// doesn't need additional authentication, then this is null.
113 8 : List<AuthenticationFlow>? get authenticationFlows => raw
114 4 : .tryGet<List<Object?>>('flows')
115 4 : ?.whereType<Map<String, Object?>>()
116 12 : .map((flow) => flow['stages'])
117 4 : .whereType<List<Object?>>()
118 8 : .map((stages) =>
119 12 : AuthenticationFlow(List<String>.from(stages.whereType<String>())))
120 4 : .toList();
121 :
122 : /// This section contains any information that the client will need to know in order to use a given type
123 : /// of authentication. For each authentication type presented, that type may be present as a key in this
124 : /// dictionary. For example, the public part of an OAuth client ID could be given here.
125 4 : Map<String, Object?>? get authenticationParams =>
126 8 : raw.tryGetMap<String, Object?>('params');
127 :
128 : /// Returns the list of already completed authentication flows from previous requests.
129 4 : List<String> get completedAuthenticationFlows =>
130 8 : raw.tryGetList<String>('completed') ?? [];
131 : }
132 :
133 : /// For each endpoint, a server offers one or more 'flows' that the client can use
134 : /// to authenticate itself. Each flow comprises a series of stages
135 : class AuthenticationFlow {
136 : final List<String> stages;
137 :
138 4 : const AuthenticationFlow(this.stages);
139 : }
|