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 import vibe.core.log: logInfo; 175 import std.conv: to; 176 logInfo(user.email().values()[0].get()); 177 178 } 179 180 /// Email Address: `class` 181 class EmailAddress 182 { 183 UUID id; 184 import std.array : split; 185 186 this(string email) 187 { 188 this.emailHandle = email.split("@")[0]; 189 this.emailDomain = email.split("@")[1]; 190 this.id = sha1UUID(emailHandle, sha1UUID(emailDomain)); 191 this.emailAddress = this.emailHandle ~ "@" ~ this.emailDomain; 192 } 193 194 private 195 { 196 197 string emailHandle; 198 string emailDomain; 199 string emailAddress; 200 } 201 202 @property string get() 203 { 204 return emailAddress; 205 } 206 207 @property string get(string input) 208 { 209 if(input == "handle") 210 { 211 return emailHandle; 212 } 213 else if(input == "domain") 214 { 215 return emailDomain; 216 } 217 else 218 { 219 throw new Error("Invalid Input Argument: only accepts \"handle\" or \"domain\""); 220 } 221 222 223 } 224 225 } 226 /// 227 unittest 228 { 229 auto address = new EmailAddress("test1@email.com"); 230 assert(is(typeof(address) == EmailAddress)); 231 assert(is(typeof(address.id) == UUID)); 232 assert(is(typeof(address.emailHandle) == string)); 233 assert(is(typeof(address.emailDomain) == string)); 234 assert(is(typeof(address.emailAddress) == string)); 235 assert(address.id == sha1UUID(address.emailHandle, sha1UUID(address.emailDomain))); 236 assert(address.emailHandle == "test1"); 237 assert(address.emailDomain == "email.com"); 238 assert(address.emailAddress == "test1@email.com"); 239 } 240 241 /// PhoneNumber: `struct` 242 struct PhoneNumber 243 { 244 UUID id; 245 string countryCode; 246 string phoneNumber; 247 string extension; 248 } 249 /// 250 unittest 251 { 252 auto number = PhoneNumber(sha1UUID("test", sha1UUID("namespace")), "44", "07999999999", "369"); 253 254 assert(is(typeof(number) == PhoneNumber)); 255 assert(is(typeof(number.id) == UUID)); 256 assert(is(typeof(number.countryCode) == string)); 257 assert(is(typeof(number.phoneNumber) == string)); 258 assert(is(typeof(number.extension) == string)); 259 assert(number.id == sha1UUID("test", sha1UUID("namespace"))); 260 assert(number.countryCode == "44"); 261 assert(number.phoneNumber == "07999999999"); 262 assert(number.extension == "369"); 263 } 264 265 /// PostalAddress - `struct` 266 struct PostalAddress 267 { 268 UUID id; 269 string buildingNumber; 270 string buildingName; 271 string unitNumber; 272 string[] streetAddress; 273 string town; 274 string city; 275 string county; 276 string country; 277 } 278 279 /// SocialAccount `struct` 280 struct SocialAccount 281 { 282 UUID id; 283 string platform; 284 string handle; 285 string homepage; 286 } 287 /// 288 unittest 289 { 290 import std.uuid : UUID, sha1UUID; 291 292 auto account = SocialAccount(sha1UUID("test", sha1UUID("namespace")), 293 "facebook", "konnex-engine", "konnex"); 294 assert(is(typeof(account) == SocialAccount)); 295 assert(is(typeof(account.id) == UUID)); 296 assert(is(typeof(account.platform) == string)); 297 assert(is(typeof(account.handle) == string)); 298 assert(is(typeof(account.homepage) == string)); 299 assert(account.id == sha1UUID("test", sha1UUID("namespace"))); 300 assert(account.platform == "facebook"); 301 assert(account.handle == "konnex-engine"); 302 assert(account.homepage == "konnex"); 303 304 } 305 306 struct DisplayName 307 { 308 UUID id; 309 string prefix; 310 string value; 311 string suffix; 312 313 DisplayName[] list = []; 314 }