1 module konnexengine.user.blueprint;
2 
3 import std.uuid : UUID, sha1UUID;
4 
5 import konnexengine.contacts.naturalperson : NaturalPersonName;
6 import konnexengine.app.data : AppData;
7 
8 /// UserInterface: `interface`	 
9 interface UserInterface
10 {
11 	@property UUID id();
12 	@property EmailAddress[UUID] email();
13 	@property string username();
14 	@property DisplayName[UUID] displayName();
15 	@property NaturalPersonName realName();
16 	@property SocialAccount[UUID] socialAccounts();
17 	@property PhoneNumber[UUID] phoneNumbers();
18 	@property PostalAddress[UUID] addresses();
19 	@property User[UUID] list();
20 }
21 
22 /// User - `class implements UserInterface`
23 class User : UserInterface
24 {
25 	this()
26 	{
27 	}
28 	// TODO: Normailse user object
29 	private
30 	{
31 		UUID u_id;
32 		EmailAddress[UUID] u_emails;
33 		string u_username;
34 		DisplayName[UUID] u_displayName;
35 		NaturalPersonName u_realName;
36 		SocialAccount[UUID] u_socials;
37 		PhoneNumber[UUID] u_numbers;
38 		PostalAddress[UUID] u_addresses;
39 		User[UUID] u_list;
40 	}
41 
42 	/// id() - `UUID`
43 	@property UUID id()
44 	{
45 		return u_id;
46 	}
47 
48 	/// id(UUID input) -`UUID`
49 	@property UUID id(UUID input)
50 	{
51 		return u_id = input;
52 	}
53 
54 	@property EmailAddress[UUID] email()
55 	{
56 		return u_emails;
57 	}
58 
59 	@property EmailAddress[UUID] email(EmailAddress input)
60 	{
61 		u_emails[input.id] = input;
62 		return u_emails;
63 	}
64 
65 	@property string username()
66 	{
67 		return u_username;
68 	}
69 
70 	@property string username(string input)
71 	{
72 		return u_username = "" ~ input;
73 	}
74 
75 	@property DisplayName[UUID] displayName()
76 	{
77 		return u_displayName;
78 	}
79 
80 	@property DisplayName[UUID] displayName(DisplayName input)
81 	{
82 		u_displayName[input.id] = input;
83 		return u_displayName;
84 	}
85 
86 	@property NaturalPersonName realName()
87 	{
88 		return u_realName;
89 	}
90 
91 	@property NaturalPersonName realName(NaturalPersonName input)
92 	{
93 		return u_realName = input;
94 	}
95 
96 	@property SocialAccount[UUID] socialAccounts()
97 	{
98 		return u_socials;
99 	}
100 
101 	@property SocialAccount[UUID] socialAccounts(SocialAccount input)
102 	{
103 		u_socials[input.id] = input;
104 		return u_socials;
105 	}
106 
107 	@property PhoneNumber[UUID] phoneNumbers()
108 	{
109 		return u_numbers;
110 	}
111 
112 	@property PhoneNumber[UUID] phoneNumbers(PhoneNumber input)
113 	{
114 		u_numbers[input.id] = input;
115 		return u_numbers;
116 	}
117 
118 	@property PostalAddress[UUID] addresses()
119 	{
120 		return u_addresses;
121 	}
122 
123 	@property PostalAddress[UUID] addresses(PostalAddress input)
124 	{
125 		u_addresses[input.id] = input;
126 		return u_addresses;
127 	}
128 
129 	@property User[UUID] list()
130 	{
131 		return u_list;
132 	}
133 
134 	@property User[UUID] list(User input)
135 	{
136 		u_list[input.id] = input;
137 		return u_list;
138 	}
139 
140 	string deleteEntry(T)(T t)
141 	{
142 		logInfo("Delete function not implemented");
143 		auto message = "" ~ typeof(t) ~ ": " ~ t.id ~ " not deleted";
144 		return "";
145 	}
146 }
147 ///
148 unittest
149 {
150 	import std.conv : to;
151 
152 	User[UUID] users;
153 	for (ushort i = 1; i <= 10; i++)
154 	{
155 		auto user = new User();
156 		auto testID = sha1UUID("test" ~ i.to!string, sha1UUID("namespace"));
157 		user.id(testID);
158 		auto testemail = new EmailAddress("test" ~ i.to!string ~ "@email.com");
159 		user.email(testemail);
160 		user.username("test" ~ i.to!string);
161 		users[user.id] = user;
162 	}
163 
164 	assert(is(typeof(users) == User[UUID]));
165 
166 	auto user = users[users.keys()[0]];
167 	assert(is(typeof(user) == User));
168 	assert(is(typeof(user.id) == UUID));
169 	assert(is(typeof(user.email) == EmailAddress[UUID]));
170 	assert(is(typeof(user.username) == string));
171 	assert(user.id() == sha1UUID(user.username, sha1UUID("namespace")));
172 	assert(user.email() == user.email());
173 	assert(user.username() == user.username);
174 
175 }
176 
177 /// Email Address: `class`
178 class EmailAddress
179 {
180 	UUID id;
181 	import std.array : split;
182 
183 	this(string email)
184 	{
185 		this.emailHandle = email.split("@")[0];
186 		this.emailDomain = email.split("@")[1];
187 		this.id = sha1UUID(emailHandle, sha1UUID(emailDomain));
188 		this.emailAddress = this.emailHandle ~ "@" ~ this.emailDomain;
189 	}
190 
191 	private
192 	{
193 
194 		string emailHandle;
195 		string emailDomain;
196 		string emailAddress;
197 	}
198 
199 	@property string get()
200 	{
201 		return emailAddress;
202 	}
203 
204 	@property string get(string input)
205 	{
206 		return emailAddress = "" ~ input;
207 	}
208 
209 }
210 ///
211 unittest
212 {
213 	auto address = new EmailAddress("test1@email.com");
214 	assert(is(typeof(address) == EmailAddress));
215 	assert(is(typeof(address.id) == UUID));
216 	assert(is(typeof(address.emailHandle) == string));
217 	assert(is(typeof(address.emailDomain) == string));
218 	assert(is(typeof(address.emailAddress) == string));
219 	assert(address.id == sha1UUID(address.emailHandle, sha1UUID(address.emailDomain)));
220 	assert(address.emailHandle == "test1");
221 	assert(address.emailDomain == "email.com");
222 	assert(address.emailAddress == "test1@email.com");
223 }
224 
225 /// PhoneNumber: `struct`
226 struct PhoneNumber
227 {
228 	UUID id;
229 	string countryCode;
230 	string phoneNumber;
231 	string extension;
232 }
233 ///
234 unittest
235 {
236 	auto number = PhoneNumber(sha1UUID("test", sha1UUID("namespace")), "44", "07999999999", "369");
237 
238 	assert(is(typeof(number) == PhoneNumber));
239 	assert(is(typeof(number.id) == UUID));
240 	assert(is(typeof(number.countryCode) == string));
241 	assert(is(typeof(number.phoneNumber) == string));
242 	assert(is(typeof(number.extension) == string));
243 	assert(number.id == sha1UUID("test", sha1UUID("namespace")));
244 	assert(number.countryCode == "44");
245 	assert(number.phoneNumber == "07999999999");
246 	assert(number.extension == "369");
247 }
248 
249 /// PostalAddress - `struct`
250 struct PostalAddress
251 {
252 	UUID id;
253 	string buildingNumber;
254 	string buildingName;
255 	string unitNumber;
256 	string[] streetAddress;
257 	string town;
258 	string city;
259 	string county;
260 	string country;
261 }
262 
263 /// SocialAccount `struct`
264 struct SocialAccount
265 {
266 	UUID id;
267 	string platform;
268 	string handle;
269 	string homepage;
270 }
271 ///
272 unittest
273 {
274 	import std.uuid : UUID, sha1UUID;
275 
276 	auto account = SocialAccount(sha1UUID("test", sha1UUID("namespace")),
277 			"facebook", "konnex-engine", "konnex");
278 	assert(is(typeof(account) == SocialAccount));
279 	assert(is(typeof(account.id) == UUID));
280 	assert(is(typeof(account.platform) == string));
281 	assert(is(typeof(account.handle) == string));
282 	assert(is(typeof(account.homepage) == string));
283 	assert(account.id == sha1UUID("test", sha1UUID("namespace")));
284 	assert(account.platform == "facebook");
285 	assert(account.handle == "konnex-engine");
286 	assert(account.homepage == "konnex");
287 
288 }
289 
290 struct DisplayName
291 {
292 	UUID id;
293 	string prefix;
294 	string value;
295 	string suffix;
296 
297 	DisplayName[] list = [];
298 }