public static DbxObject Register(Instance instance, string type, string email, string password) { // Check email isn't already in use var objs = instance.LocateEq(type, Locate.GenerateSimple("email", email)); // TODO: Race condition? if (objs.Count > 0) throw new UserErrorException("auth.ambigious", "Invalid address, email already in use '" + email + "'"); // Calculate auth factors var salt = Util.GenerateSalt(32); var authhash = GenerateAuthHash(email, password, salt); // Create object var properties = new Dictionary<string, object>(); properties["email"] = email; properties["authhash"] = authhash; properties["salt"] = salt; return instance.Create(type, "system", properties); }
public override DbxObject GetObject(Instance instance, string type, object rawauthdata) { DbxObject obj; string access_token; string partner = null; bool tos = false; try { var authdata = (Dictionary<string, object>)rawauthdata; // Get access_token access_token = (string)authdata["access_token"]; // Try and get partneruid if (authdata.ContainsKey("partner")) partner = (string)authdata["partner"]; // Try and get TOS if (authdata.ContainsKey("tos")) tos = (bool)authdata["tos"]; } catch { throw new UserErrorException("parameter.invalid", "auth; Invalid form"); } // Perform FB query string result; try { result = Facebook.WebGet("https://graph.facebook.com/me?fields=id,name,first_name,last_name,link,email,timezone,locale,verified,updated_time&access_token=" + Common.Util.UrlEncode(access_token)); } catch (OAuthException) { throw new ObjectNotExistException(); } // Convert response to objects var ret = new Dictionary<string, object>(); try { ret = Common.Util.JsonDeserialize<Dictionary<string, object>>(result); } catch (Exception) { throw new UserErrorException("upstream", "Unexpected response from Facebook"); } // Extract key values if (ret["id"].ToString() == "0" || ret["id"].ToString() == "") throw new UserErrorException("upstream", "Invalid FBID returned from Facebook"); var fbid = Util.ParseNumber(ret["id"]); string email = ""; if (ret.ContainsKey("email")) email = ((string)ret["email"]).ToLowerInvariant(); // Calculate properties var props = new Dictionary<string, object>(); props["email"] = email; props["fbid"] = fbid; props["creatorModule"] = "auth"; if (ret.ContainsKey("name")) props["dname"] = ret["name"]; if (ret.ContainsKey("name")) props["aname"] = ret["name"]; if (ret.ContainsKey("fbLink")) props["fbLink"] = ret["link"]; if (ret.ContainsKey("fbTimezone")) props["fbTimezone"] = ret["timezone"]; if (ret.ContainsKey("fbLocale")) props["fbLocale"] = ret["locale"]; if (ret.ContainsKey("fbVerified")) props["fbVerified"] = ret["verified"]; if (ret.ContainsKey("fbUpdated")) props["fbUpdated"] = ret["updated_time"]; if (tos) props["tos"] = true; if (null != partner) { // Check object exists try { obj = instance.Uid("partner$" + partner); } catch (ObjectNotExistException) { throw new UserErrorException("parameter.invalid", "Invalid partner reference in 'partner'"); } // Set property props["partner"] = "partner$" + partner; } // Plan A: Try search by ID var objs = instance.LocateEq("user", Locate.GenerateSimple("fbid", fbid)); if (objs.Count == 0) { // User not found, create obj = instance.Create("user", "system", props); } else { // User found, update // Find oldest record (HACK: To handle ambigious matches) obj = objs[0]; foreach (var item in objs) { if (item.Predecessor > 0 && item.Predecessor < obj.Predecessor) obj = item; }; obj = obj.GetWritableInstance(); obj.Set(props, "system"); } // Enforce TOS if (!((bool)obj.GetProp("tos", "system"))) throw new UserErrorException("auth.prerequisite.tos", "Terms of Service has not yet been accepted"); return obj; }