public RESTReplyData user_friends_post(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { bodyUserFriendsPost body = pReq.RequestBodyObject <bodyUserFriendsPost>(); string friendname = body.username; Context.Log.Debug("{0} user_friends_post: adding friend {1} for user {2}", _logHeader, body.username, aAccount.Username); if (Accounts.Instance.TryGetAccountWithUsername(friendname, out AccountEntity _)) { if (!aAccount.Friends.Contains(friendname)) { aAccount.Friends.Add(friendname); } } else { Context.Log.Error("{0} user_friends_post: attempt to add friend that does not exist. Requestor={1}, friend={2}", _logHeader, aAccount.Username, friendname); respBody.RespondFailure("Attempt to add friend that does not exist"); } } else { Context.Log.Error("{0} GET user/friends requested without auth token. Token={1}", _logHeader, pReq.AuthToken); respBody.RespondFailure("Unauthorized"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData put_ice_address(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity aDomain)) { // Context.Log.Debug("{0} domains/ice_server_addr PUT. Body={1}", _logHeader, pReq.RequestBody); bodyIceServerPut isr = pReq.RequestBodyObject <bodyIceServerPut>(); string includeAPIKey = isr.domain.api_key; if (String.IsNullOrEmpty(aDomain.API_Key) || includeAPIKey == aDomain.API_Key) { aDomain.IceServerAddr = isr.domain.ice_server_address; } else { respBody.RespondFailure(); replyData.Status = 401; // not authorized } } else { respBody.RespondFailure(); replyData.Status = 404; } return(replyData); }
public RESTReplyData put_ice_address(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity aDomain)) { // Context.Log.Debug("{0} domains/ice_server_addr PUT. Body={1}", _logHeader, pReq.RequestBody); bodyIceServerPut isr = pReq.RequestBodyObject <bodyIceServerPut>(); string includeAPIKey = isr.domain.api_key; if (VerifyDomainAccess(aDomain, pReq, includeAPIKey, out string oFailureReason)) { aDomain.IceServerAddr = isr.domain.ice_server_address; } else { Context.Log.Error("{0} PUT domains/%/ice_server_address not authorized. DomainID={1}", _logHeader, domainID); respBody.RespondFailure(oFailureReason); replyData.Status = (int)HttpStatusCode.Unauthorized; } } else { respBody.RespondFailure("No such domain"); replyData.Status = (int)HttpStatusCode.NotFound; } return(replyData); }
public RESTReplyData admin_domain_delete(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { if (aAccount.IsAdmin) { string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity aDomain)) { Domains.Instance.RemoveDomain(aDomain); } else { respBody.RespondFailure("No such domain"); } } else { respBody.RespondFailure("Requesting account is not an administrator"); replyData.Status = (int)HttpStatusCode.Unauthorized; } } else { respBody.RespondFailure("Authorization token not found"); replyData.Status = (int)HttpStatusCode.Unauthorized; } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData user_location_set(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { try { GetAccountLocationIfSpecified(aAccount, pReq); } catch (Exception e) { Context.Log.Error("{0} PUT user/location Failed body parsing. Acct={1}: {2}", _logHeader, aAccount.AccountID, e); respBody.RespondFailure("failed location parsing", e.ToString()); } } else { respBody.RespondFailure("Unauthorized"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData set_public_key(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity aDomain)) { try { string includedAPIKey = pReq.RequestBodyMultipart("api_key"); // If this is a temp domain, the supplied API key must match // TODO: is there another Authorization later (ie, maybe user auth?) if (String.IsNullOrEmpty(aDomain.API_Key) || aDomain.API_Key == includedAPIKey) { // The PUT sends the key as binary but it is later sent around // and processed as a Base64 string. Stream byteStream = pReq.RequestBodyMultipartStream("public_key"); if (byteStream != null) { using var memStream = new MemoryStream(); byteStream.CopyTo(memStream); aDomain.Public_Key = Convert.ToBase64String(memStream.ToArray()); aDomain.Updated(); // Context.Log.Debug("{0} successful set of public_key for {1}", _logHeader, domainID); } else { Context.Log.Error("{0} could not extract public key from request body: domain {1}", _logHeader, domainID); replyData.Status = 401; // not authorized respBody.RespondFailure(); } } else { Context.Log.Error("{0} attempt to set public_key with non-matching APIKeys: domain {1}", _logHeader, domainID); replyData.Status = 401; // not authorized respBody.RespondFailure(); } } catch (Exception e) { Context.Log.Error("{0} exception parsing multi-part http: {1}", _logHeader, e.ToString()); respBody.RespondFailure(); } } else { Context.Log.Error("{0} attempt to set public_key for unknown domain {1}", _logHeader, domainID); respBody.RespondFailure(); } replyData.Body = respBody; return(replyData); }
public RESTReplyData set_public_key(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info SessionEntity aSession = Sessions.Instance.UpdateSession(pReq.SenderKey); string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity aDomain)) { try { string includedAPIKey = pReq.RequestBodyMultipart("api_key"); if (VerifyDomainAccess(aDomain, pReq, includedAPIKey, out string oFailureReason)) { // The PUT sends the key as binary but it is later sent around // and processed as a Base64 string. Stream byteStream = pReq.RequestBodyMultipartStream("public_key"); if (byteStream != null) { aDomain.Public_Key = Tools.ConvertPublicKeyStreamToBase64(byteStream); aDomain.Updated(); // Context.Log.Debug("{0} successful set of public_key for {1}", _logHeader, domainID); } else { Context.Log.Error("{0} could not extract public key from request body: domain {1}", _logHeader, domainID); replyData.Status = (int)HttpStatusCode.Unauthorized; respBody.RespondFailure("Could not extract public key from request body"); } } else { Context.Log.Error("{0} attempt to set public_key when no authorized: domain {1}", _logHeader, domainID); replyData.Status = (int)HttpStatusCode.Unauthorized; respBody.RespondFailure(oFailureReason); } } catch (Exception e) { Context.Log.Error("{0} exception parsing multi-part http: {1}", _logHeader, e.ToString()); respBody.RespondFailure("Exception parsing multi-part http", e.ToString()); } } else { Context.Log.Error("{0} attempt to set public_key for unknown domain {1}", _logHeader, domainID); respBody.RespondFailure("unknown domain"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData user_profile_gen(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { respBody.Data = new bodyUserProfileReply() { user = new bodyUserProfileInfo() { username = aAccount.Username, accountid = aAccount.AccountID, xmpp_password = aAccount.xmpp_password, discourse_api_key = aAccount.discourse_api_key, wallet_id = aAccount.wallet_id } }; } else { Context.Log.Error("{0} GET user/profile requested without auth token. Token={1}", _logHeader, pReq.AuthToken); respBody.RespondFailure("Unauthorized"); } replyData.SetBody(respBody, pReq); // Context.Log.Debug("{0} GET user/profile. Response={1}", _logHeader, replyData.Body); return(replyData); }
public RESTReplyData get_public_key(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); string username = pArgs.Count == 1 ? pArgs[0] : null; if (Accounts.Instance.TryGetAccountWithUsername(username, out AccountEntity aAccount)) { respBody.Data = new bodyUserPublicKeyReply() { public_key = aAccount.Public_Key, username = aAccount.Username, accountid = aAccount.AccountID }; } else { Context.Log.Error("{0} GET fetch of user public key for unknown acct. SenderKey: {1}, Username: {2}", _logHeader, pReq.SenderKey, username); respBody.RespondFailure("Unknown username"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData admin_get_accounts(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { PaginationInfo pagination = new PaginationInfo(pReq); AccountFilterInfo acctFilter = new AccountFilterInfo(pReq); AccountScopeFilter scopeFilter = new AccountScopeFilter(pReq, aAccount); respBody.Data = new bodyAccountsReply() { accounts = Accounts.Instance.Enumerate(pagination, acctFilter, scopeFilter).Select(acct => { return(new bodyAccountInfo(acct)); }).ToArray() }; } else { Context.Log.Error("{0} GET accounts requested with bad auth", _logHeader); respBody.RespondFailure("Bad authorization"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData get_public_key(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity aDomain)) { respBody.Data = new bodyDomainPublicKeyGetResponse() { public_key = aDomain.Public_Key }; } else { // return nothing! respBody.RespondFailure(); respBody.Data = new Dictionary <string, string>() { { "domain", "there is no domain with that ID" } }; replyData.Status = 404; // Context.Log.Debug("{0} get_domain GET: no domain! Returning: {1}", _logHeader, replyData.Body); } replyData.Body = respBody; // serializes JSON return(replyData); }
public RESTReplyData get_domains(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { PaginationInfo pagination = new PaginationInfo(pReq); respBody.Data = new bodyDomainsReply() { domains = Domains.Instance.Enumerate(pagination).Select(dom => { return(new bodyDomainInfo(dom)); }).ToArray() }; } else { respBody.RespondFailure("Unauthorized"); replyData.Status = (int)HttpStatusCode.Unauthorized; } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData get_public_key(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity aDomain)) { respBody.Data = new bodyDomainPublicKeyGetResponse() { public_key = aDomain.Public_Key }; } else { // return nothing! respBody.RespondFailure("unknown domain"); respBody.ErrorData("domain", "there is no domain with that ID"); // legacy HiFi compatibility replyData.Status = (int)HttpStatusCode.NotFound; // Context.Log.Debug("{0} get_domain GET: no domain! Returning: {1}", _logHeader, replyData.Body); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData get_domain(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity dobj)) { respBody.Data = new bodyDomainResponse() { domain = new bodyDomainReplyData() { id = domainID, ice_server_address = dobj.GetIceServerAddr(), name = dobj.PlaceName } }; } else { // return nothing! respBody.RespondFailure("No domain with that ID"); respBody.ErrorData("domain", "there is no domain with that ID"); replyData.Status = (int)HttpStatusCode.NotFound; } replyData.SetBody(respBody, pReq); return(replyData); }
/// <summary> /// Do an API operation where one account is operating on a targetted account. /// Takes all the request parameters and an operation to perfrom on the target account. /// The target account is specified by an accountID as the first parameter in the /// request URL. /// </summary> /// <remarks> /// The requesting account must be the target account or an administration account. /// </remarks> /// <param name="pReq"></param> /// <param name="pArgs"></param> /// <param name="pDoOp"></param> /// <returns></returns> public RESTReplyData APITargetedAccountOperation(RESTRequestData pReq, List <string> pArgs, DoOperation pDoOp) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { string otherAcct = pArgs.Count > 0 ? pArgs[0] : null; if (otherAcct != null) { if (Accounts.Instance.TryGetAccountWithID(otherAcct, out AccountEntity targetAccount)) { // either the requestor is admin or the same account if (aAccount.Administrator || aAccount.AccountID == targetAccount.AccountID) { pDoOp(respBody, aAccount, targetAccount); } else { respBody.RespondFailure("Not account or administrator"); replyData.Status = (int)HttpStatusCode.Unauthorized; }; } else { respBody.RespondFailure("No such account"); replyData.Status = (int)HttpStatusCode.Unauthorized; }; } else { respBody.RespondFailure("Account not included in request URL"); } } else { respBody.RespondFailure("Unauthorized"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData get_location(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { // aAccount = the requesting account // TODO: lookup the specified user and see if requestor can see their location string otherAccountName = pArgs.Count == 1 ? pArgs[0] : null; if (!String.IsNullOrEmpty(otherAccountName)) { // Convert the %20's to spaces, etc otherAccountName = HttpUtility.UrlDecode(otherAccountName); if (Accounts.Instance.TryGetAccountWithUsername(otherAccountName, out AccountEntity otherAccount)) { // Using only one field in 'bodyUser', others will be null and thus not sent respBody.Data = new bodyUser() { location = BuildLocationInfo(aAccount) }; } else { respBody.RespondFailure("No such username"); } } else { respBody.RespondFailure("Target account not included in URL"); } } else { Context.Log.Error("{0} GET user/location requested without auth token. Token={1}", _logHeader, pReq.AuthToken); respBody.RespondFailure("Unauthorized"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData user_locker_get(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { respBody.Data = aAccount.AccountSettings; } else { Context.Log.Error("{0} GET user/locker requested without auth token. Token={1}", _logHeader, pReq.AuthToken); respBody.RespondFailure("Unauthorized"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData user_heartbeat(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info SessionEntity aSession = Sessions.Instance.UpdateSession(pReq.SenderKey); if (!String.IsNullOrEmpty(pReq.AuthToken)) { // The user thinks they are logged in, update location info if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { aAccount.TimeOfLastHeartbeat = DateTime.UtcNow; GetAccountLocationIfSpecified(aAccount, pReq); respBody.Data = new bodyUserHeartbeatResponse() { session_id = aSession?.SessionID }; } else { // Who is this clown? replyData.Status = (int)HttpStatusCode.Unauthorized; respBody.RespondFailure("Unauthorized"); Context.Log.Error("{0} Heartbeat from account with non-matching token. Sender={1}", _logHeader, pReq.SenderKey); } } else { // A new heartbeat from a new place. // Is this a non-logged in user? Context.Log.Info("{0} Heartbeat from unknown sender {1}", _logHeader, pReq.SenderKey); respBody.Data = new bodyUserHeartbeatResponse() { session_id = aSession?.SessionID }; } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData user_connections_delete(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); string connectionname = pArgs.Count == 1 ? pArgs[0] : null; if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { Context.Log.Debug("{0} user_connections_delete: removing connection {1} for user {2}", _logHeader, connectionname, aAccount.Username); aAccount.Friends.Remove(connectionname); } else { Context.Log.Error("{0} DELETE user/connections requested without auth token. Token={1}", _logHeader, pReq.AuthToken); respBody.RespondFailure("Unauthorized"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData get_domain(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity dobj)) { respBody.Data = new bodyDomainResponse() { domain = new bodyDomainReplyData() { id = domainID, ice_server_address = dobj.GetIceServerAddr(), name = dobj.PlaceName } }; replyData.Body = respBody; // serializes JSON // Context.Log.Debug("{0} get_domain GET: domain{1}, returning: {2}", // _logHeader, domainID, replyData.Body); } else { // return nothing! respBody.RespondFailure(); respBody.Data = new Dictionary <string, string>() { { "domain", "there is no domain with that ID" } }; replyData.Status = 404; replyData.Body = respBody; // Context.Log.Debug("{0} get_domain GET: no domain! Returning: {1}", _logHeader, replyData.Body); } return(replyData); }
public RESTReplyData new_scope_token(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); if (Sessions.Instance.ShouldBeThrottled(pReq.SenderKey, Sessions.Op.TOKEN_CREATE)) { respBody.RespondFailure("Throttled"); respBody.Data = new { operation = "throttled" }; } else { // Getting a token for a domain server if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity oAccount)) { AuthTokenInfo token = null; string scope = pReq.Queries.ContainsKey("scope") ? pReq.Queries["scope"] : "owner"; switch (scope) { case "domain": token = oAccount.CreateAccessToken(AuthTokenInfo.ScopeCode.domain); // The domain/account association lasts longer token.TokenExpirationTime = new DateTime(2999, 12, 31); break; case "owner": token = oAccount.CreateAccessToken(AuthTokenInfo.ScopeCode.owner); break; default: break; } if (token != null) { respBody.Data = new { token = token.Token, token_id = token.TokenId, refresh_token = token.RefreshToken, token_expiration_seconds = (int)(token.TokenExpirationTime - token.TokenCreationTime).TotalSeconds, account_name = oAccount.Username, account_type = oAccount.GetAccountType(), account_id = oAccount.AccountID }; } else { respBody.RespondFailure("Token could not be generated. Bad scope?"); } } else { // Not a known account. respBody.RespondFailure("Unknown requesting account"); } } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData user_create(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info if (Sessions.Instance.ShouldBeThrottled(pReq.SenderKey, Sessions.Op.ACCOUNT_CREATE)) { respBody.RespondFailure("Throttled"); respBody.ErrorData("error", "throttled"); } else { try { bodyUsersPost requestData = pReq.RequestBodyObject <bodyUsersPost>(); string userName = requestData.user["username"]; string userPassword = requestData.user["password"]; string userEmail = requestData.user["email"]; if (CheckUsernameFormat(userName)) { if (CheckEmailFormat(userEmail)) { Context.Log.Debug("{0} Creating account {1}/{2}", _logHeader, userName, userEmail); AccountEntity newAcct = Accounts.Instance.CreateAccount(userName, userPassword, userEmail); if (newAcct == null) { respBody.RespondFailure("Username already exists"); respBody.ErrorData("username", "already exists"); // legacy HiFi compatibility Context.Log.Debug("{0} Failed acct creation. Username already exists. User={1}", _logHeader, userName); } else { // Successful account creation newAcct.IPAddrOfCreator = pReq.SenderKey; newAcct.Updated(); Context.Log.Debug("{0} Successful acct creation. User={1}", _logHeader, userName); } } else { respBody.RespondFailure("Bad format for email"); respBody.ErrorData("error", "bad format for email"); } } else { respBody.RespondFailure("Bad format for username"); respBody.ErrorData("error", "bad format for username"); } } catch (Exception e) { replyData.Status = (int)HttpStatusCode.BadRequest; Context.Log.Error("{0} Badly formed create account request. {1}", _logHeader, e); } } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData domain_heartbeat(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); // The request's "data" response info SessionEntity aSession = Sessions.Instance.UpdateSession(pReq.SenderKey); string domainID = pArgs.Count == 1 ? pArgs[0] : null; if (Domains.Instance.TryGetDomainWithID(domainID, out DomainEntity aDomain)) { try { // Since the body has a lot of optional fields, we need to pick // through what's sent so we only set what was sent. JObject requestData = pReq.RequestBodyJSON(); JObject domainStuff = (JObject)requestData["domain"]; string apiKey = (string)domainStuff["api_key"]; // Context.Log.Debug("{0} domain_heartbeat. Received {1}", _logHeader, pReq.RequestBody); if (VerifyDomainAccess(aDomain, pReq, apiKey, out string oFailureReason)) { Tools.SetIfSpecified <string>(domainStuff, "version", ref aDomain.Version); Tools.SetIfSpecified <string>(domainStuff, "protocol", ref aDomain.Protocol); Tools.SetIfSpecified <string>(domainStuff, "network_address", ref aDomain.NetworkAddr); Tools.SetIfSpecified <string>(domainStuff, "automatic_networking", ref aDomain.NetworkingMode); Tools.SetIfSpecified <bool>(domainStuff, "restricted", ref aDomain.Restricted); Tools.SetIfSpecified <int>(domainStuff, "capacity", ref aDomain.Capacity); Tools.SetIfSpecified <string>(domainStuff, "description", ref aDomain.Description); Tools.SetIfSpecified <string>(domainStuff, "maturity", ref aDomain.Maturity); Tools.SetIfSpecified <string>(domainStuff, "restriction", ref aDomain.Restriction); JArray hosts = (JArray)domainStuff["hosts"]; if (hosts != null) { aDomain.Hosts = domainStuff["hosts"].ToObject <string[]>(); } JArray tags = (JArray)domainStuff["tags"]; if (tags != null) { aDomain.Tags = domainStuff["tags"].ToObject <string[]>(); } JObject heartbeat = (JObject)domainStuff["heartbeat"]; if (heartbeat != null) { Tools.SetIfSpecified <int>(heartbeat, "num_users", ref aDomain.NumUsers); Tools.SetIfSpecified <int>(heartbeat, "num_anon_users", ref aDomain.AnonUsers); aDomain.TotalUsers = aDomain.NumUsers + aDomain.AnonUsers; // TODO: what to do with user_hostnames } aDomain.TimeOfLastHeartbeat = DateTime.UtcNow; aDomain.LastSenderKey = pReq.SenderKey; aDomain.Updated(); } else { Context.Log.Error("{0} domain_heartbeat with bad authorization. domainID={1}", _logHeader, domainID); respBody.RespondFailure(oFailureReason); replyData.Status = (int)HttpStatusCode.Unauthorized; } } catch (Exception e) { Context.Log.Error("{0} domain_heartbeat: Exception processing body: {1}", _logHeader, e.ToString()); respBody.RespondFailure("exception processing body", e.ToString()); replyData.Status = (int)HttpStatusCode.BadRequest; } } else { Context.Log.Error("{0} domain_heartbeat: unknown domain. Returning 404", _logHeader); respBody.RespondFailure("no such domain"); replyData.Status = (int)HttpStatusCode.NotFound; // this will trigger a new temporary domain name } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData set_public_key(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); string includedAPIKey = null; string includedPublicKey = null; bool parsed = false; // whether multipart was parsed try { // The PUT sends the key as binary but it is later sent around // and processed as a Base64 string. Stream byteStream = pReq.RequestBodyMultipartStream("public_key"); if (byteStream != null) { includedPublicKey = Tools.ConvertPublicKeyStreamToBase64(byteStream); // There might has been an APIKey includedAPIKey = pReq.RequestBodyMultipart("api_key"); parsed = true; } else { Context.Log.Error("{0} could not extract public key from request body in PUT user/public_key", _logHeader); } } catch (Exception e) { Context.Log.Error("{0} exception parsing multi-part http: {1}", _logHeader, e.ToString()); parsed = false; } if (parsed) { // If there is account authorization in the header, set the account public key. // If no account authorization (the client is not logged in), check for matching // APIkey and then set the session public key. if (String.IsNullOrEmpty(pReq.AuthToken)) { if (includedAPIKey != null && Domains.Instance.TryGetDomainWithAPIKey(includedAPIKey, out DomainEntity aDomain)) { aDomain.Public_Key = includedPublicKey; } else { Context.Log.Error("{0} PUT user/set_public_key requested without APIKey. APIKey={1}", _logHeader, includedAPIKey); respBody.RespondFailure("APIkey does not work"); replyData.Status = (int)HttpStatusCode.Unauthorized; } } else { if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { aAccount.Public_Key = includedPublicKey; } else { Context.Log.Error("{0} PUT user/set_public_key requested but could not find acct. Token={1}", _logHeader, pReq.AuthToken); respBody.RespondFailure("AuthToken unauthorized"); replyData.Status = (int)HttpStatusCode.Unauthorized; } } } else { Context.Log.Error("{0} PUT user/set_public_key failure parsing", _logHeader); respBody.RespondFailure("Multi-part body failed parsing"); } replyData.SetBody(respBody, pReq); return(replyData); }
public RESTReplyData user_connections_request_post(RESTRequestData pReq, List <string> pArgs) { RESTReplyData replyData = new RESTReplyData(); // The HTTP response info ResponseBody respBody = new ResponseBody(); if (Accounts.Instance.TryGetAccountWithAuthToken(pReq.AuthToken, out AccountEntity aAccount)) { bodyUserConnectionRequestPost request = pReq.RequestBodyObject <bodyUserConnectionRequestPost>(); // The script looks for two types of 'connection' responses. // If is sees data.connection == "pending", it trys again and eventually times out // If data.connection has an object, it uses 'new_connection' and 'username' // Connection handles are the in-world nodeId's string thisNode = request.user_connection_request.node_id; string otherNode = request.user_connection_request.proposed_node_id; // BEGIN sanity check DEBUG DEBUG { // Connections use node id's to identify the two avatars, I guess because, the // world does not have access to the account identity. // This debugging code prints out whether the passed nodeIds match the loction // nodeIds that we have to verify that the connection nodeIds are really the // same ones as passed in the location. // All this debugging output can go away once nodeId usage is understood. Context.Log.Debug("{0} connection_request: request from account '{1}' node={2}, proposed={3}", _logHeader, aAccount.Username, thisNode, otherNode); if (aAccount.Location != null) { if (aAccount.Location.NodeID == thisNode) { Context.Log.Debug("{0} connection_request: request from account '{1}' and Location.NodeId matches main node", _logHeader, aAccount.Username); } else { if (aAccount.Location.NodeID == otherNode) { Context.Log.Debug("{0} connection_request: request from account '{1}' and Location.NodeId matches proposed node", _logHeader, aAccount.Username); } else { Context.Log.Debug("{0} connection_request: request from account '{1}' and Location.NodeId does not match either nodes", _logHeader, aAccount.Username); } } } else { Context.Log.Debug("{0} connection_request: request from account '{1}' and no location info", _logHeader, aAccount.Username); } } // END sanity check DEBUG DEBUG try { // This returns all the RequestConnection's that have my ID in them RequestConnection previousAsk = RequestConnection.GetNodeRequests(thisNode) // Find the ones that have me and the other requestor .Where(req => { return((req.Body.node_id == thisNode && req.Body.proposed_node_id == otherNode) || (req.Body.node_id == otherNode && req.Body.proposed_node_id == thisNode)); // Pick the one (there should be only one) }).FirstOrDefault(); if (previousAsk != null) { Context.Log.Debug("{0} connection_request: existing request found", _logHeader); // We have a pending connection request for this person // Mark myself as accepting if (previousAsk.Body.node_id == thisNode) { if (!previousAsk.Body.node_accepted) { previousAsk.Body.node_accepted = true; previousAsk.Updated(); } } else { if (!previousAsk.Body.proposed_node_accepted) { previousAsk.Body.proposed_node_accepted = true; previousAsk.Updated(); } // I'm in the 'proposed node' position. // Straighten out the node variables for simplier logic after this var tmp = otherNode; otherNode = thisNode; thisNode = tmp; // after this, "thisNode" is always this account Context.Log.Debug("{0} connection_request: found request was from other account", _logHeader); } // If both accepted, the connection is complete if (previousAsk.Body.node_accepted && previousAsk.Body.proposed_node_accepted) { if (Accounts.Instance.TryGetAccountWithNodeId(otherNode, out AccountEntity oOtherAccount)) { aAccount.AddConnection(oOtherAccount); aAccount.Updated(); oOtherAccount.AddConnection(aAccount); oOtherAccount.Updated(); respBody.Data = new { connection = new { new_connection = true, // says whether a new or pre-existing connection username = oOtherAccount.Username } }; } else { // Can't find the other account... shouldn't happen respBody.RespondFailure("Both agreed but cannot find other account entity"); } } else { // Both haven't accepted so tell the requestor that the request is pending respBody.Data = new Dictionary <string, string>() { { "connection", "pending" } }; } } else { // There was no previous ask so create the request. Context.Log.Debug("{0} connection_request: creating connection request from '{1}", _logHeader, aAccount.Username); RequestConnection newReq = new RequestConnection(); newReq.Body.node_id = thisNode; newReq.Body.requestor_accountId = aAccount.AccountID; newReq.Body.proposed_node_id = otherNode; newReq.Body.node_accepted = true; newReq.ExpireIn(TimeSpan.FromSeconds(Context.Params.P <int>(AppParams.P_CONNECTION_REQUEST_SECONDS))); newReq.AddAndUpdate(); // Both haven't accepted so tell the requestor that the request is pending respBody.Data = new Dictionary <string, string>() { { "connection", "pending" } }; } } catch { } } else { Context.Log.Error("{0} POST user/connection_request for unauthorized user. Token={1}", _logHeader, pReq.AuthToken); respBody.RespondFailure("Unauthorized"); } replyData.SetBody(respBody, pReq); return(replyData); }