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 7 : String get errcode =>
72 14 : raw.tryGet<String>('errcode') ??
73 2 : (requireAdditionalAuthentication ? 'M_FORBIDDEN' : 'M_UNKNOWN');
74 :
75 : /// A human readable error description.
76 5 : String get errorMessage =>
77 10 : 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 5 : @override
91 15 : 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 18 : 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 4 : .map(
119 4 : (stages) =>
120 12 : AuthenticationFlow(List<String>.from(stages.whereType<String>())),
121 : )
122 4 : .toList();
123 :
124 : /// This section contains any information that the client will need to know in order to use a given type
125 : /// of authentication. For each authentication type presented, that type may be present as a key in this
126 : /// dictionary. For example, the public part of an OAuth client ID could be given here.
127 4 : Map<String, Object?>? get authenticationParams =>
128 8 : raw.tryGetMap<String, Object?>('params');
129 :
130 : /// Returns the list of already completed authentication flows from previous requests.
131 4 : List<String> get completedAuthenticationFlows =>
132 8 : raw.tryGetList<String>('completed') ?? [];
133 : }
134 :
135 : /// For each endpoint, a server offers one or more 'flows' that the client can use
136 : /// to authenticate itself. Each flow comprises a series of stages
137 : class AuthenticationFlow {
138 : final List<String> stages;
139 :
140 4 : const AuthenticationFlow(this.stages);
141 : }
|