1 /** 2 Parameter validation types transparently supported for web interface methods. 3 4 Copyright: © 2014 RejectedSoftware e.K. 5 License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 6 Authors: Sönke Ludwig 7 */ 8 module hb.web.validation; 9 10 import vibe.utils.validation; 11 12 import std.array : appender; 13 import std.typecons : Nullable; 14 15 16 /** 17 Validated e-mail parameter type. 18 19 See_also: $(D vibe.utils.validation.validateEmail) 20 */ 21 struct ValidEmail { 22 private string m_value; 23 24 private this(string value) { m_value = value; } 25 @disable this(); 26 27 string toString() const pure nothrow @safe { return m_value; } 28 alias toString this; 29 30 static Nullable!ValidEmail fromStringValidate(string str, string* error) 31 { 32 // work around disabled default construction 33 Nullable!ValidEmail ret = Nullable!ValidEmail(ValidEmail(null)); 34 ret.nullify(); 35 36 auto err = appender!string(); // TODO: avoid allocations when possible 37 if (validateEmail(err, str)) ret = ValidEmail(str); 38 else *error = err.data; 39 return ret; 40 } 41 } 42 43 /// 44 unittest { 45 class WebService { 46 void setEmail(ValidEmail email) 47 { 48 // email is enforced to be valid here 49 } 50 51 void updateProfileInfo(Nullable!ValidEmail email, Nullable!string full_name) 52 { 53 // email is optional, but always valid 54 // full_name is optional and not validated 55 } 56 } 57 } 58 59 60 /** 61 Validated user name parameter type. 62 63 See_also: $(D vibe.utils.validation.validateUsername) 64 */ 65 struct ValidUsername { 66 private string m_value; 67 68 private this(string value) { m_value = value; } 69 @disable this(); 70 71 string toString() const pure nothrow @safe { return m_value; } 72 alias toString this; 73 74 static Nullable!ValidUsername fromStringValidate(string str, string* error) 75 { 76 // work around disabled default construction 77 Nullable!ValidUsername ret = Nullable!ValidUsername(ValidUsername(null)); 78 ret.nullify(); 79 80 auto err = appender!string(); // TODO: avoid allocations when possible 81 if (validateUserName(err, str)) ret = ValidUsername(str); 82 else *error = err.data; 83 return ret; 84 } 85 } 86 87 /// 88 unittest { 89 class WebService { 90 void setUsername(ValidUsername username) 91 { 92 // username is enforced to be valid here 93 } 94 95 void updateProfileInfo(Nullable!ValidUsername username, Nullable!string full_name) 96 { 97 // username is optional, but always valid 98 // full_name is optional and not validated 99 } 100 } 101 } 102 103 104 /** 105 Validated password parameter. 106 107 See_also: $(D vibe.utils.validation.validatePassword) 108 */ 109 struct ValidPassword { 110 private string m_value; 111 112 private this(string value) { m_value = value; } 113 @disable this(); 114 115 string toString() const pure nothrow @safe { return m_value; } 116 alias toString this; 117 118 static Nullable!ValidPassword fromStringValidate(string str, string* error) 119 { 120 // work around disabled default construction 121 Nullable!ValidPassword ret = Nullable!ValidPassword(ValidPassword(null)); 122 ret.nullify(); 123 124 auto err = appender!string(); // TODO: avoid allocations when possible 125 if (validatePassword(err, str, str)) ret = ValidPassword(str); 126 else *error = err.data; 127 return ret; 128 } 129 } 130 131 132 /** 133 Ensures that the parameter value matches that of another parameter. 134 */ 135 struct Confirm(string CONFIRMED_PARAM) 136 { 137 enum confirmedParameter = CONFIRMED_PARAM; 138 139 private string m_value; 140 141 string toString() const pure nothrow @safe { return m_value; } 142 alias toString this; 143 144 static Confirm fromString(string str) { return Confirm(str); } 145 } 146 147 /// 148 unittest { 149 class WebService { 150 void setPassword(ValidPassword password, Confirm!"password" password_confirmation) 151 { 152 // password is valid and guaranteed to equal password_confirmation 153 } 154 155 void setProfileInfo(string full_name, Nullable!ValidPassword password, Nullable!(Confirm!"password") password_confirmation) 156 { 157 // Password is valid and guaranteed to equal password_confirmation 158 // It is allowed for both, password and password_confirmation 159 // to be absent at the same time, but not for only one of them. 160 } 161 } 162 }