[AllowAnonymous] // will check security internally, so assume no requirements public IEnumerable <Dictionary <string, object> > GetEntities(string contentType, string appPath = null, string cultureCode = null) { var wraplog = Log.Call($"get entities type:{contentType}, path:{appPath}, culture:{cultureCode}"); // if app-path specified, use that app, otherwise use from context var appIdentity = AppFinder.GetAppIdFromPathOrContext(appPath, BlockBuilder); // verify that read-access to these content-types is permitted var permCheck = new MultiPermissionsTypes(BlockBuilder, appIdentity.AppId, contentType, Log); if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var exp)) { throw exp; } //2018-09-15 2dm replaced //var context = GetContext(SxcBlock, Log); //PerformSecurityCheck(appIdentity, contentType, Grants.Read, appPath == null ? context.Dnn.Module : null); var result = new EntityApi(appIdentity.AppId, permCheck.EnsureAny(GrantSets.ReadDraft), Log) .GetEntities(contentType, cultureCode) ?.ToList(); wraplog("found: " + result?.Count); return(result); }
internal IEnumerable <Dictionary <string, object> > GetItems(IInstanceContext context, string contentType, IBlock ctxBlock, string appPath = null) { var wrapLog = Log.Call($"get entities type:{contentType}, path:{appPath}"); // if app-path specified, use that app, otherwise use from context var appIdentity = AppFinder.GetAppIdFromPathOrContext(appPath, ctxBlock); // get the app - if we have the context from the request, use that, otherwise generate full app var app = ctxBlock == null ? Factory.Resolve <Apps.App>().Init(appIdentity, Log) : GetApp(appIdentity.AppId, ctxBlock); // verify that read-access to these content-types is permitted var permCheck = new MultiPermissionsTypes().Init(context, app, contentType, Log); if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var error)) { throw HttpException.PermissionDenied(error); } var result = new EntityApi(appIdentity.AppId, permCheck.EnsureAny(GrantSets.ReadDraft), Log) .GetEntities(contentType) ?.ToList(); wrapLog("found: " + result?.Count); return(result); }
public IEnumerable <Dictionary <string, object> > GetAllOfTypeForAdmin(int appId, string contentType) { var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log); if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var exception)) { throw exception; } return(new EntityApi(appId, Log).GetEntitiesForAdmin(contentType)); }
public Dictionary <string, object> GetOne(string contentType, int id, int appId, string cultureCode = null) { var permCheck = new MultiPermissionsTypes(BlockBuilder, appId, contentType, Log); if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var exception)) { throw exception; } return(new EntityApi(appId, true, Log).GetOne(contentType, id, cultureCode)); // note that the culture-code isn't actually used... }
public void Delete(string contentType, Guid guid, int appId, bool force = false) { var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log); if (!permCheck.EnsureAll(GrantSets.DeleteSomething, out var exception)) { throw exception; } new EntityApi(appId, Log).Delete(contentType, guid, force); }
public AllInOne Load([FromBody] List <ItemIdentifier> items, int appId) { // Security check var wraplog = Log.Call("Load", $"load many a#{appId}, items⋮{items.Count}"); // do early permission check - but at this time it may be that we don't have the types yet // because they may be group/id combinations, without type information which we'll look up afterwards var appForSecurityChecks = App.LightWithoutData(new DnnTenant(PortalSettings), appId, Log); items = new SaveHelpers.ContentGroupList(SxcInstance, Log).ConvertListIndexToId(items, appForSecurityChecks); // now look up the types, and repeat security check with type-names var permCheck = new MultiPermissionsTypes(SxcInstance, appId, items, Log); if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var exception)) { throw exception; } // load items - similar var result = new AllInOne(); var entityApi = new EntityApi(appId, Log); var typeRead = entityApi.AppManager.Read.ContentTypes; var list = entityApi.GetEntitiesForEditing(appId, items); var jsonSerializer = new JsonSerializer(); result.Items = list.Select(e => new BundleWithHeader <JsonEntity> { Header = e.Header, Entity = jsonSerializer.ToJson(e.Entity ?? ConstructEmptyEntity(appId, e.Header, typeRead)) }).ToList(); // set published if some data already exists if (list.Any()) { result.IsPublished = list.First().Entity?.IsPublished ?? true; // Entity could be null (new), then true } // load content-types var types = UsedTypes(list, typeRead); result.ContentTypes = types.Select(ct => JsonSerializer.ToJson(ct, true)).ToList(); // load input-field configurations result.InputTypes = GetNecessaryInputTypes(types, typeRead); // also deliver features result.Features = SystemController.FeatureListWithPermissionCheck(appId, permCheck).ToList(); // done - return wraplog($"ready, sending items:{result.Items.Count}, " + $"types:{result.ContentTypes.Count}, " + $"inputs:{result.InputTypes.Count}, " + $"feats:{result.Features.Count}"); return(result); }
public Dictionary <string, object> GetOne(string contentType, int id, int appId, string cultureCode = null) { var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log); if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var exception)) { throw exception; } // 2018-09-15 old code, should have checked the same stuff mostly... //new AppPermissionBeforeUsing(SxcInstance, Log) // .ConfirmPermissionsOrThrow(contentType, appId, Grants.Read); return(new EntityApi(appId, Log).GetOne(contentType, id, cultureCode)); // note that the culture-code isn't actually used... }
public void Delete(string contentType, Guid guid, int appId, bool force = false) { var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log); if (!permCheck.EnsureAll(GrantSets.DeleteSomething, out var exception)) { throw exception; } // 2018-09-15 old code, should have checked the same stuff mostly... //new AppPermissionBeforeUsing(SxcInstance, Log) // .ConfirmPermissionsOrThrow(contentType, appId, GrantSets.DeleteSomething); new EntityApi(appId, Log).Delete(contentType, guid, force); }
public IEnumerable <Dictionary <string, object> > GetAllOfTypeForAdmin(int appId, string contentType) { var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentType, Log); if (!permCheck.EnsureAll(GrantSets.ReadSomething, out var exception)) { throw exception; } // 2018-09-15 old code, should have checked the same stuff mostly... //new AppPermissionBeforeUsing(SxcInstance, Log) // .ConfirmPermissionsOrThrow(contentType, appId, Grants.Read); return(new EntityApi(appId, Log).GetEntitiesForAdmin(contentType)); }
public IEnumerable <ContentTypeFieldInfo> GetFields(int appId, string staticName) { Log.Add($"get fields for a:{appId} type:{staticName}"); var permCheck = new MultiPermissionsTypes(SxcInstance, appId, staticName, Log); if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var exp)) { throw exp; } if (!permCheck.UserCanWriteAndPublicFormsEnabled(out exp)) { throw exp; } return(_eavCtc.GetFields(appId, staticName)); }
public dynamic GetSingle(int appId, string contentTypeStaticName, string scope = null) { var permCheck = new MultiPermissionsTypes(SxcInstance, appId, contentTypeStaticName, Log); if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var exp)) { throw exp; } if (!permCheck.UserCanWriteAndPublicFormsEnabled(out exp)) { throw exp; } // if we got this far, permissions are ok return(_eavCtc.GetSingle(appId, contentTypeStaticName, scope)); }
public IMultiPermissionCheck DoPreSaveSecurityCheck(int appId, IEnumerable <BundleWithHeader> items) { var app = Factory.Resolve <Apps.App>().Init(appId, Log, Block); var permCheck = new MultiPermissionsTypes().Init(Block.Context, app, items.Select(i => i.Header).ToList(), Log); if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var error)) { throw HttpException.PermissionDenied(error); } if (!permCheck.UserCanWriteAndPublicFormsEnabled(out _, out error)) { throw HttpException.PermissionDenied(error); } Log.Add("passed security checks"); return(permCheck); }
/// <summary> /// Initializes the object and performs all the initial security checks /// </summary> public virtual AdamContext Init(IContextOfApp context, string contentType, string fieldName, Guid entityGuid, bool usePortalRoot, ILog parentLog) { Log.LinkTo(parentLog); var appId = context.AppState.AppId; var callLog = Log.Call <AdamContext>($"app: {context.AppState.Show()}, field:{fieldName}, guid:{entityGuid}"); Context = context; Permissions = ServiceProvider.Build <MultiPermissionsTypes>() .Init(context, context.AppState, contentType, Log); // only do checks on field/guid if it's actually accessing that, if it's on the portal root, don't. UseSiteRoot = usePortalRoot; if (!usePortalRoot) { ItemField = fieldName; ItemGuid = entityGuid; } Security = ServiceProvider.Build <AdamSecurityChecksBase>().Init(this, usePortalRoot, Log); if (Security.MustThrowIfAccessingRootButNotAllowed(usePortalRoot, out var exception)) { throw exception; } Log.Add("check if feature enabled"); if (Security.UserIsRestricted && !Eav.Configuration.Features.Enabled(FeaturesForRestrictedUsers)) { throw HttpException.PermissionDenied( $"low-permission users may not access this - {Eav.Configuration.Features.MsgMissingSome(FeaturesForRestrictedUsers)}"); } if (string.IsNullOrEmpty(contentType) || string.IsNullOrEmpty(fieldName)) { return(callLog(null, this)); } Attribute = AttributeDefinition(appId, contentType, fieldName); if (!Security.FileTypeIsOkForThisField(out var exp)) { throw exp; } return(callLog(null, this)); }
public IMultiPermissionCheck DoPreSaveSecurityCheck(int appId, IEnumerable <BundleWithHeader> items) { var permCheck = new MultiPermissionsTypes(SxcInstance, appId, items.Select(i => i.Header).ToList(), Log); if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var exp)) { throw exp; } if (!permCheck.UserCanWriteAndPublicFormsEnabled(out exp)) { throw exp; } // 2018-09-26 2dm // add test to verify that saving existing items is allowed Log.Add("passed security checks"); return(permCheck); }
public dynamic GetManyForEditing([FromBody] List <ItemIdentifier> items, int appId) { var wrapLog = Log.Call("GetManyForEditing", $"get many a#{appId}, items⋮{items.Count}"); // before we start, we have to convert the indexes into something more useful, because // otherwise in content-list scenarios we don't have the type var appForSecurityChecks = App.LightWithoutData(new DnnTenant(PortalSettings), SystemRuntime.ZoneIdOfApp(appId), appId, Log); items = new SaveHelpers.ContentGroupList(SxcInstance, Log).ConvertListIndexToId(items, appForSecurityChecks); // to do full security check, we'll have to see what content-type is requested var permCheck = new MultiPermissionsTypes(SxcInstance, appId, items, Log); if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var exception)) { throw exception; } var list = new EntityApi(appId, Log).GetEntitiesForEditing(appId, items); // Reformat to the Entity-WithLanguage setup var listAsEwH = list.Select(p => new BundleWithHeader <EntityWithLanguages> { Header = p.Header, Entity = p.Entity != null ? EntityWithLanguages.Build(appId, p.Entity) : null }).ToList(); // 2018-09-26 2dm // if we're giving items which already exist, then we must verify that edit/read is allowed. // important, this code is shared/duplicated in the UiController.Load if (list.Any(set => set.Entity != null)) { if (!permCheck.EnsureAll(GrantSets.ReadSomething, out exception)) { throw exception; } } wrapLog($"will return items⋮{list.Count}"); return(listAsEwH); }
/// <summary> /// Initializes the object and performs all the initial security checks /// </summary> protected AdamState(IBlock block, int appId, string contentType, string field, Guid guid, bool usePortalRoot, ILog log) : base("Adm.State", log) { var callLog = Log.Call($"field:{field}, guid:{guid}"); App = Factory.Resolve <Apps.App>().Init(appId, log, block); Permissions = new MultiPermissionsTypes() .Init(block.Context, App, contentType, Log); Block = block; // only do checks on field/guid if it's actually accessing that, if it's on the portal root, don't. UseTenantRoot = usePortalRoot; if (!usePortalRoot) { ItemField = field; ItemGuid = guid; } Security = Factory.Resolve <SecurityChecksBase>().Init(this, usePortalRoot, Log); SecurityCheckHelpers.ThrowIfAccessingRootButNotAllowed(usePortalRoot, Security.UserIsRestricted); Log.Add("check if feature enabled"); if (Security.UserIsRestricted && !ToSic.Eav.Configuration.Features.Enabled(FeaturesForRestrictedUsers)) { throw HttpException.PermissionDenied( $"low-permission users may not access this - {ToSic.Eav.Configuration.Features.MsgMissingSome(FeaturesForRestrictedUsers)}"); } PrepCore(App, guid, field, usePortalRoot); if (string.IsNullOrEmpty(contentType) || string.IsNullOrEmpty(field)) { return; } Attribute = Definition(appId, contentType, field); if (!Security.FileTypeIsOkForThisField(out var exp)) { throw exp; } callLog(null); }
public AllInOne Load([FromBody] List <ItemIdentifier> items, int appId) { // Security check var wraplog = Log.Call($"load many a#{appId}, items⋮{items.Count}"); // do early permission check - but at this time it may be that we don't have the types yet // because they may be group/id combinations, without type information which we'll look up afterwards var appIdentity = State.Identity(null, appId); items = new ContentGroupList(BlockBuilder, Log).ConvertListIndexToId(items, appIdentity); // now look up the types, and repeat security check with type-names // todo: 2020-03-20 new feat 11.01, may not check inner type permissions ATM var permCheck = new MultiPermissionsTypes(BlockBuilder, appId, items, Log); if (!permCheck.EnsureAll(GrantSets.WriteSomething, out var exception)) { throw exception; } // load items - similar var result = new AllInOne(); var entityApi = new EntityApi(appId, permCheck.EnsureAny(GrantSets.ReadDraft), Log); var typeRead = entityApi.AppRead.ContentTypes; var list = entityApi.GetEntitiesForEditing(appId, items); var jsonSerializer = new JsonSerializer(); result.Items = list.Select(e => new BundleWithHeader <JsonEntity> { Header = e.Header, Entity = GetSerializeAndMdAssignJsonEntity(appId, e, jsonSerializer, typeRead) }).ToList(); // set published if some data already exists if (list.Any()) { result.IsPublished = list.First().Entity?.IsPublished ?? true; // Entity could be null (new), then true // only set draft-should-branch if this draft already has a published item if (!result.IsPublished) { result.DraftShouldBranch = list.First().Entity?.GetPublished() != null; } } // since we're retrieving data - make sure we're allowed to // this is to ensure that if public forms only have create permissions, they can't access existing data // important, this code is shared/duplicated in the EntitiesController.GetManyForEditing if (list.Any(set => set.Entity != null)) { if (!permCheck.EnsureAll(GrantSets.ReadSomething, out exception)) { throw exception; } } // load content-types var types = UsedTypes(list, typeRead); result.ContentTypes = types .Select(ct => JsonSerializer.ToJson(ct, true)) .ToList(); // todo: ensure that sub-properties of the content-types are included var entList = types.SelectMany( // in all Content-Type attributes like title, body etc. t => t.Attributes.SelectMany( // check all metadata of these attributes - get possible sub-entities attached a => a.Metadata.SelectMany(m => m.Children()) ) ); result.ContentTypeItems = entList.Select(e => jsonSerializer.ToJson(e, 0, Log)).ToList(); // Fix not-supported input-type names; map to correct name result.ContentTypes .ForEach(jt => jt.Attributes .ForEach(at => at.InputType = InputTypes.MapInputTypeV10(at.InputType))); // load input-field configurations result.InputTypes = GetNecessaryInputTypes(result.ContentTypes, typeRead); // also include UI features result.Features = SystemController.FeatureListWithPermissionCheck(permCheck).ToList(); // done - return wraplog($"ready, sending items:{result.Items.Count}, " + $"types:{result.ContentTypes.Count}, " + $"inputs:{result.InputTypes.Count}, " + $"feats:{result.Features.Count}"); return(result); }