diff --git a/docs/8.0/ayanova/docs/api-response-format.md b/docs/8.0/ayanova/docs/api-response-format.md index 8ed53fbe..e492320f 100644 --- a/docs/8.0/ayanova/docs/api-response-format.md +++ b/docs/8.0/ayanova/docs/api-response-format.md @@ -17,12 +17,13 @@ All successful GET responses have a standard format: "id": 150, "name": "Handmade Rubber Pizza", ...etc... - } + }, + "readOnly": boolean } ``` The results of the response are always contained in the `data` property and could be a single object, a collection or in some cases nothing at all. -HTTP Status Code is set in the header. +HTTP Status Code is set in the header. A ReadOnly property is set on the returned data for the convenience of the client software however note that the server will always determine this independently so if this property is ignored and the client attempts to update the record a error 2004 NOT_AUTHORIZED would be returned. ### GET COLLECTION RESPONSE diff --git a/server/AyaNova/ControllerHelpers/ApiOkResponse.cs b/server/AyaNova/ControllerHelpers/ApiOkResponse.cs index e535ef76..52828a9b 100644 --- a/server/AyaNova/ControllerHelpers/ApiOkResponse.cs +++ b/server/AyaNova/ControllerHelpers/ApiOkResponse.cs @@ -8,10 +8,12 @@ namespace AyaNova.Api.ControllerHelpers { public object Data { get; } + public bool ReadOnly {get;} - public ApiOkResponse(object result) + public ApiOkResponse(object result, bool isReadOnly) { Data = result; + ReadOnly=isReadOnly; } }//eoc diff --git a/server/AyaNova/Controllers/AttachmentController.cs b/server/AyaNova/Controllers/AttachmentController.cs index 4e6ab605..d1d83736 100644 --- a/server/AyaNova/Controllers/AttachmentController.cs +++ b/server/AyaNova/Controllers/AttachmentController.cs @@ -104,7 +104,7 @@ namespace AyaNova.Api.Controllers log.LogInformation("Auth retry dlkey"); }; - return Ok(new ApiOkResponse(new { dlkey = u.DlKey, expires = u.DlKeyExpire })); + return Ok(new ApiOkResponse(new { dlkey = u.DlKey, expires = u.DlKeyExpire }, true)); } } @@ -247,7 +247,7 @@ namespace AyaNova.Api.Controllers } //Return the list of attachment ids and filenames - return Ok(new ApiOkResponse(returnList)); + return Ok(new ApiOkResponse(returnList, false)); } /// diff --git a/server/AyaNova/Controllers/AuthController.cs b/server/AyaNova/Controllers/AuthController.cs index 560d64d6..caafcc29 100644 --- a/server/AyaNova/Controllers/AuthController.cs +++ b/server/AyaNova/Controllers/AuthController.cs @@ -29,7 +29,7 @@ namespace AyaNova.Api.Controllers private readonly IConfiguration _configuration; private readonly ApiServerState serverState; private readonly IMetrics metrics; - private const int JWT_LIFETIME_DAYS=7; + private const int JWT_LIFETIME_DAYS = 7; /// /// ctor @@ -120,7 +120,7 @@ namespace AyaNova.Api.Controllers }; string TestToken = Jose.JWT.Encode(payload, secretKey, Algorithm); - + //Post JWT creation test payloads switch (creds.Password) { @@ -129,9 +129,9 @@ namespace AyaNova.Api.Controllers break; case "TRANSPOSE_SIGNATURE": //Transpose two characters in the signature - int len=TestToken.Length; - var Transposed = TestToken.Substring(0,len-5) + TestToken[len-4] + TestToken[len-5] + TestToken.Substring(len-3,3); - TestToken=Transposed; + int len = TestToken.Length; + var Transposed = TestToken.Substring(0, len - 5) + TestToken[len - 4] + TestToken[len - 5] + TestToken.Substring(len - 3, 3); + TestToken = Transposed; break; } @@ -139,7 +139,7 @@ namespace AyaNova.Api.Controllers return Ok(new ApiOkResponse(new { token = TestToken - })); + }, true)); } @@ -181,7 +181,7 @@ namespace AyaNova.Api.Controllers { //This is leaking information, instead just act like bad creds //return StatusCode(401, new ApiErrorResponse(ApiErrorCode.NOT_AUTHORIZED, null, "User deactivated")); - return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED)); + return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED)); } //build the key (JWT set in startup.cs) @@ -218,7 +218,7 @@ namespace AyaNova.Api.Controllers token = token //, //id = u.Id - })); + }, true)); } } diff --git a/server/AyaNova/Controllers/AyaEnumPickListController.cs b/server/AyaNova/Controllers/AyaEnumPickListController.cs index 53818944..d74ceb84 100644 --- a/server/AyaNova/Controllers/AyaEnumPickListController.cs +++ b/server/AyaNova/Controllers/AyaEnumPickListController.cs @@ -129,7 +129,7 @@ namespace AyaNova.Api.Controllers } - return Ok(new ApiOkResponse(ReturnList)); + return Ok(new ApiOkResponse(ReturnList, true)); } @@ -154,7 +154,7 @@ namespace AyaNova.Api.Controllers ret.Add(new KeyValuePair("authorizationroles", "AyaNova user account role types")); ret.Add(new KeyValuePair("AyaType", "All AyaNova object types, use the AyaTypeController route to fetch these")); - return Ok(new ApiOkResponse(ret)); + return Ok(new ApiOkResponse(ret, true)); } diff --git a/server/AyaNova/Controllers/AyaTypeController.cs b/server/AyaNova/Controllers/AyaTypeController.cs index 7923a8ec..4c89252a 100644 --- a/server/AyaNova/Controllers/AyaTypeController.cs +++ b/server/AyaNova/Controllers/AyaTypeController.cs @@ -70,7 +70,7 @@ namespace AyaNova.Api.Controllers } - return Ok(new ApiOkResponse(l)); + return Ok(new ApiOkResponse(l, true)); } diff --git a/server/AyaNova/Controllers/DataFilterController.cs b/server/AyaNova/Controllers/DataFilterController.cs index 3517a39c..01c6f60f 100644 --- a/server/AyaNova/Controllers/DataFilterController.cs +++ b/server/AyaNova/Controllers/DataFilterController.cs @@ -71,7 +71,7 @@ namespace AyaNova.Api.Controllers if (o == null) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); - return Ok(new ApiOkResponse(o)); + return Ok(new ApiOkResponse(o, !Authorized.IsAuthorizedToModify(HttpContext.Items, biz.BizType))); } @@ -96,7 +96,7 @@ namespace AyaNova.Api.Controllers DataFilterBiz biz = DataFilterBiz.GetBiz(ct, HttpContext); var l = await biz.GetPickListAsync(ListKey); - return Ok(new ApiOkResponse(l)); + return Ok(new ApiOkResponse(l, true)); } @@ -142,7 +142,7 @@ namespace AyaNova.Api.Controllers else return StatusCode(409, new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT)); } - return Ok(new ApiOkResponse(new { ConcurrencyToken = o.ConcurrencyToken })); + return Ok(new ApiOkResponse(new { ConcurrencyToken = o.ConcurrencyToken }, true)); } diff --git a/server/AyaNova/Controllers/EventLogController.cs b/server/AyaNova/Controllers/EventLogController.cs index 52ed4155..5ca48033 100644 --- a/server/AyaNova/Controllers/EventLogController.cs +++ b/server/AyaNova/Controllers/EventLogController.cs @@ -67,7 +67,7 @@ namespace AyaNova.Api.Controllers } var result = await EventLogProcessor.GetLogForObject(opt, ct); - return Ok(new ApiOkResponse(result)); + return Ok(new ApiOkResponse(result, true)); } @@ -104,7 +104,7 @@ namespace AyaNova.Api.Controllers var result = await EventLogProcessor.GetLogForUser(opt, ct); - return Ok(new ApiOkResponse(result)); + return Ok(new ApiOkResponse(result, true)); } diff --git a/server/AyaNova/Controllers/FormCustomController.cs b/server/AyaNova/Controllers/FormCustomController.cs index d8820c50..8fc08531 100644 --- a/server/AyaNova/Controllers/FormCustomController.cs +++ b/server/AyaNova/Controllers/FormCustomController.cs @@ -87,7 +87,7 @@ namespace AyaNova.Api.Controllers } } - return Ok(new ApiOkResponse(o)); + return Ok(new ApiOkResponse(o, !Authorized.IsAuthorizedToModify(HttpContext.Items, biz.BizType))); } @@ -117,7 +117,7 @@ namespace AyaNova.Api.Controllers if (FormAvailableFields.IsValidFormKey(formkey)) { - return Ok(new ApiOkResponse(FormAvailableFields.FormFields(formkey))); + return Ok(new ApiOkResponse(FormAvailableFields.FormFields(formkey), true)); } else { @@ -145,7 +145,7 @@ namespace AyaNova.Api.Controllers if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - return Ok(new ApiOkResponse(AyDataType.ValidCustomFieldTypes)); + return Ok(new ApiOkResponse(AyDataType.ValidCustomFieldTypes, true)); } @@ -169,7 +169,7 @@ namespace AyaNova.Api.Controllers if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - return Ok(new ApiOkResponse(FormAvailableFields.AvailableFormKeys)); + return Ok(new ApiOkResponse(FormAvailableFields.AvailableFormKeys, true)); } @@ -215,7 +215,7 @@ namespace AyaNova.Api.Controllers else return StatusCode(409, new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT)); } - return Ok(new ApiOkResponse(new { ConcurrencyToken = o.ConcurrencyToken })); + return Ok(new ApiOkResponse(new { ConcurrencyToken = o.ConcurrencyToken }, true)); } diff --git a/server/AyaNova/Controllers/ImportAyaNova7Controller.cs b/server/AyaNova/Controllers/ImportAyaNova7Controller.cs index ce2e41d3..9f6fbdc9 100644 --- a/server/AyaNova/Controllers/ImportAyaNova7Controller.cs +++ b/server/AyaNova/Controllers/ImportAyaNova7Controller.cs @@ -138,7 +138,7 @@ namespace AyaNova.Api.Controllers } //Return the list of attachment ids and filenames - return Ok(new ApiOkResponse(returnList)); + return Ok(new ApiOkResponse(returnList, true)); } @@ -204,7 +204,7 @@ namespace AyaNova.Api.Controllers //dump file name example: ayanova.data.dump.XXX.zip List l = FileUtil.UtilityFileList("ayanova.data.dump.*.zip"); - return Ok(new ApiOkResponse(l)); + return Ok(new ApiOkResponse(l, true)); } diff --git a/server/AyaNova/Controllers/JobOperationsController.cs b/server/AyaNova/Controllers/JobOperationsController.cs index 1a94954c..8652eee6 100644 --- a/server/AyaNova/Controllers/JobOperationsController.cs +++ b/server/AyaNova/Controllers/JobOperationsController.cs @@ -77,7 +77,7 @@ namespace AyaNova.Api.Controllers JobOperationsBiz biz = new JobOperationsBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); List l = await biz.GetJobListAsync(); - return Ok(new ApiOkResponse(l)); + return Ok(new ApiOkResponse(l, true)); } @@ -116,7 +116,7 @@ namespace AyaNova.Api.Controllers JobOperationsBiz biz = new JobOperationsBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); List l = await biz.GetJobLogListAsync(gid); - return Ok(new ApiOkResponse(l)); + return Ok(new ApiOkResponse(l, true)); } diff --git a/server/AyaNova/Controllers/LicenseController.cs b/server/AyaNova/Controllers/LicenseController.cs index 5d8ecca0..241e76c9 100644 --- a/server/AyaNova/Controllers/LicenseController.cs +++ b/server/AyaNova/Controllers/LicenseController.cs @@ -67,7 +67,7 @@ namespace AyaNova.Api.Controllers var ret = AyaNova.Core.License.LicenseInfoAsJson; - return Ok(new ApiOkResponse(ret)); + return Ok(new ApiOkResponse(ret, true)); } @@ -129,7 +129,7 @@ namespace AyaNova.Api.Controllers //Log EventLogProcessor.LogEventToDatabase(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseFetch), ct); - return Ok(new ApiOkResponse(ret)); + return Ok(new ApiOkResponse(ret, true)); } @@ -181,7 +181,7 @@ namespace AyaNova.Api.Controllers //Log EventLogProcessor.LogEventToDatabase(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseTrialRequest), ct); - return Ok(new ApiOkResponse(ret)); + return Ok(new ApiOkResponse(ret, true)); } //------------------------------------------------------ diff --git a/server/AyaNova/Controllers/LocaleController.cs b/server/AyaNova/Controllers/LocaleController.cs index d3023692..5e32f07b 100644 --- a/server/AyaNova/Controllers/LocaleController.cs +++ b/server/AyaNova/Controllers/LocaleController.cs @@ -82,7 +82,7 @@ namespace AyaNova.Api.Controllers return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); } - return Ok(new ApiOkResponse(o)); + return Ok(new ApiOkResponse(o, true)); } @@ -106,7 +106,7 @@ namespace AyaNova.Api.Controllers LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); var l = await biz.GetPickListAsync(); - return Ok(new ApiOkResponse(l)); + return Ok(new ApiOkResponse(l, true)); } @@ -130,7 +130,7 @@ namespace AyaNova.Api.Controllers //LocaleBiz biz = new LocaleBiz(ct, UserIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items)); var l = biz.LocaleKeyCoverage(); - return Ok(new ApiOkResponse(l)); + return Ok(new ApiOkResponse(l, true)); } #endif @@ -157,7 +157,7 @@ namespace AyaNova.Api.Controllers LocaleBiz biz = LocaleBiz.GetBiz(ct, HttpContext); var l = await biz.GetSubset(inObj); - return Ok(new ApiOkResponse(l)); + return Ok(new ApiOkResponse(l, true)); } @@ -265,7 +265,7 @@ namespace AyaNova.Api.Controllers } - return Ok(new ApiOkResponse(new { ConcurrencyToken = oFromDb.ConcurrencyToken })); + return Ok(new ApiOkResponse(new { ConcurrencyToken = oFromDb.ConcurrencyToken }, true)); } /// @@ -331,7 +331,7 @@ namespace AyaNova.Api.Controllers } } - return Ok(new ApiOkResponse(new { ConcurrencyToken = oFromDb.ConcurrencyToken })); + return Ok(new ApiOkResponse(new { ConcurrencyToken = oFromDb.ConcurrencyToken }, true)); } diff --git a/server/AyaNova/Controllers/WidgetController.cs b/server/AyaNova/Controllers/WidgetController.cs index 6a0ce696..9d077918 100644 --- a/server/AyaNova/Controllers/WidgetController.cs +++ b/server/AyaNova/Controllers/WidgetController.cs @@ -74,7 +74,7 @@ namespace AyaNova.Api.Controllers if (o == null) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND)); - return Ok(new ApiOkResponse(o)); + return Ok(new ApiOkResponse(o, !Authorized.IsAuthorizedToModify(HttpContext.Items, biz.BizType))); }