-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexample.dart
189 lines (163 loc) · 6.01 KB
/
example.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Chain of Responsibility is behavioral design pattern
// that allows passing request along the chain of potential handlers
// until one of them handles request.
// The pattern allows multiple objects to handle the request
// without coupling sender class to the concrete classes of the receivers.
// The chain can be composed dynamically at runtime
// with any handler that follows a standard handler interface.
// Usage examples:
// it’s only relevant when code operates with chains of objects.
// One of the most popular use cases for the pattern is bubbling events to the parent components in GUI classes.
// Another notable use case is sequential access filters.
// Identification:
// The pattern is recognizable by behavioral methods of one group of objects
// that indirectly call the same methods in other objects,
// while all the objects follow the common interface.
// Filtering access
// This example shows how a request containing user data passes a sequential chain of handlers
// that perform various things such as authentification, authorization, and validation.
// This example is a bit different from the canonical version of the pattern given by various authors.
// Most of the pattern examples are built on the notion of looking for the right handler,
// launching it and exiting the chain after that.
// ""But here we execute every handler until there’s one that can’t handle a request."""
// Be aware that this still is the Chain of Responsibility pattern,
// even though the flow is a bit different.
abstract class Middleware {
Middleware? _next;
/// Builds chains of middleware objects.
Middleware linkWith(Middleware next) {
_next = next;
return next;
}
/// Runs check on the next object in chain or ends traversing if we're in
/// last object in chain.
bool checkNext(String email, String password) {
if (_next == null) {
return true;
} else {
return _next!.check(email, password);
}
}
/// Subclasses will implement this method with concrete checks.
bool check(String email, String password);
}
/// Check _request amount limit
/// ConcreteHandler. Checks whether there are too many failed login _requests.
class ThrottlingMiddleware extends Middleware {
int _requestPerMinute;
int? _request;
int _currentTime;
ThrottlingMiddleware(int requestPerMinute)
: _requestPerMinute = requestPerMinute,
_currentTime = DateTime.now().millisecond;
/**
* Please, not that checkNext() call can be inserted both in the beginning
* of this method and in the end.
*
* This gives much more flexibility than a simple loop over all middleware
* objects. For instance, an element of a chain can change the order of
* checks by running its check after all other checks.
*/
@override
bool check(String email, String password) {
if (DateTime.now().millisecond > _currentTime + 60000) {
_request = 0;
_currentTime = DateTime.now().millisecond;
}
if (_request != null) {
_request = _request! + 1;
} else {
_request = 0;
}
if (_request! > _requestPerMinute) {
print("_Request limit exceeded!");
print('---stop!!');
}
return checkNext(email, password);
}
}
// Check user’s credentials
// ConcreteHandler. Checks whether a user with the given credentials exists.
class UserExistsMiddleware extends Middleware {
Server _server;
UserExistsMiddleware(Server server) : _server = server;
@override
bool check(String email, String password) {
if (!_server.hasEmail(email)) {
print("This email is not registered!");
return false;
}
if (!_server.isValidPassword(email, password)) {
print("Wrong password!");
return false;
}
return checkNext(email, password);
}
}
// Check user’s role
class RoleCheckMiddleware extends Middleware {
@override
bool check(String email, String password) {
if (email == "[email protected]") {
print("Hello, admin!");
return true;
}
print("Hello, user!");
return checkNext(email, password);
}
}
// Authorization target
// Server class.
class Server {
final Map<String, String> _users = {};
late Middleware _middleware;
/**
* Client passes a chain of object to server. This improves flexibility and
* makes testing the server class easier.
*/
void setMiddleware(Middleware middleware) => _middleware = middleware;
/**
* Server gets email and password from client and sends the authorization
* _request to the chain.
*/
bool logIn(String email, String password) {
if (_middleware.check(email, password)) {
print("Authorization have been successful!");
// check mail and password .
if (email.contains('@') && password.length >= 4) {
return true;
} else {
return false;
}
}
return false;
}
void register(String email, String password) => _users[email] = password;
bool hasEmail(String email) => _users.containsKey(email);
bool isValidPassword(String email, String password) =>
_users[email] == password;
}
/// Demo main(). Everything comes together here.
void main() {
Server server = Server();
server.register("[email protected]", "admin_pass");
server.register("[email protected]", "user_pass");
// All checks are linked. Client can build various chains using the same
// components.
Middleware middleware = ThrottlingMiddleware(2);
middleware
.linkWith(UserExistsMiddleware(server))
.linkWith(RoleCheckMiddleware());
// Server gets a chain from client code.
server.setMiddleware(middleware);
print("----------------will fail----------------");
server.logIn("hello", "password");
server.logIn("hello@fish", "password");
server.logIn("hello@fish", "a");
server.logIn("[email protected]", "pas");
server.logIn("[email protected]", "password2");
print("----------------will success admin----------------");
server.logIn("[email protected]", "admin_pass");
print("----------------will success user----------------");
server.logIn("[email protected]", "user_pass");
}