GithubHelp home page GithubHelp logo

raythahq / raytha Goto Github PK

View Code? Open in Web Editor NEW
132.0 6.0 27.0 38.99 MB

Raytha is a powerful CMS with an easy-to-use interface and fast performance. It offers custom content types, a template engine, and various access controls. It supports multiple storage providers and an automatically generated REST API. Upgrade your development workflow with Raytha.

License: MIT License

TSQL 2.42% C# 52.16% Liquid 1.03% HTML 18.18% Dockerfile 0.06% CSS 23.09% JavaScript 3.06%
cms content-management-system csharp dotnet rad-framework headless-cms

raytha's People

Contributors

apexdodge avatar brendonofficial avatar dependabot[bot] avatar divyeshio avatar harshjain1707 avatar ibrahimbagalwa avatar jimreed91 avatar kanareklife avatar killbut avatar smd-11 avatar soumya-kushwaha avatar takuabonn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

raytha's Issues

Setup DocFx and Getting Started docs

Did some rudimentary testing with DocFX and it was easy to get started.

https://dotnet.github.io/docfx/index.html

I ran it on the Raytha.Application project and it did a thorough job of picking up literally everything.

image

Need to learn how to properly format and clean it up.

Ideally, the left side navigation is simply:

  • Admins

    • Commands.CreateAdmin
    • Commands.DeleteAdmin
    • Commands.EditAdmin
    • Queries.GetAdminById
    • Queries.GetAdmins
    • EventHandlers.AdminCreatedEventHandler
    • EventHandlers.AdminPasswordResetEventHandler
  • ContentItems

    • Commands.CreateContentItem
    • Commands.DeleteContentItem

...etc, etc, basically just the business layer actions, nicely organized.

I created a branch called docfx

Include variable for View and ContentType descriptions in templates

Both Views and Content Types have "Description" fields that are option when creating / editing. It would be very helpful to have these descriptions available inside the templates, potentially for SEO meta descriptions.

Example:

image

Task:

  • Update RenderModel on ContentType to include Description
  • Update RenderModel on View to include Description
  • Update GetProjection methods to map

Add support for AddDataProtection()

When running Raytha in kubernetes and scaling up to more than 1 pod of Raytha, I noticed it loses the login sometimes. This is because we did not implement services.AddDataProtection().

There are a few ways to implement, but keeping it the simplest and technology footprint minimal, we will use the PersistKeysToDbContext as outlined here: https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-7.0#persistkeystodbcontext

services.AddDataProtection().SetApplicationName("Raytha").PersistKeysToDbContext<RaythaDbContext>();

I tested it and it works, but this will be slated for 1.0 milestone because it has a database migration script.

RAD - Generate the boilerplate classes from Entity

Hello, this is simply awesome, with its simplicity, love the videos as well, I highly encourage others to view them.

Can you help explain, how we can create the various hooks, classes if we have entities, for e.g. EventManagement, with all its supporting needs. Will there be a T4 template or some code gen.
Also whats your road map, and can we use this in a commercial closed source for free

thanks

Block user from deleting Template if a content item uses that template

Currently, if you delete a template, the associated content items are silently deleted and I believe this is unexpected behavior. Better to err on the side of caution and prevent this.

Task:

  • If a system admin attempts to delete a template, show an error message saying that Content Items are making use of this template. Those content items should be moved to another template prior to deletion.

Running in 'Debug without JS' has a solution error

When loading up the code base for the first time and changing to Debug without JS configuration mode, a message pops up saying that the solution is misconfigured. Updating it is easy, but should not have this error in the first place.

Build in `BackgroundJob` infrastructure

We need to be able run background jobs or long running jobs such as full data exports / data imports / web hooks, and anything else that may be best served running outside the main web request.

Neither Quartz, nor Hangfire are MIT license. So we may have to roll our own.

Dropdown field goes blank if you submit form that fails validation.

If you choose a field in a drop down box (possibly radio also), and then submit, but something caused a validation failure on the form submission, then the drop down field does not keep its value and you have to re-select it.

image

Task:

  • Ensure that on save, if a dropdown box had a value, it keeps the value on validation failure.
  • Check to see if this is impacting Radio Fields as well.

Detailed error message missing on template editing

Since we moved to the new Monaco Editor, if the user has a validation error when submitting the form, the page just says "There were errors that occurred, see below for details", but no details appear.

Add a custom filter to make it convenient to point to a file

See custom liquid filter here:

https://deanebarker.net/tech/fluid/custom-filters/

As of v0.9.2 the template author has to remember to link to attached files like so:

/raytha/media-items/objectkey/{{ Target.PublishedContent.attachment.Value }}

I think this is unfair to expect the template author to remember the prefix of file route. Instead, we can easily do a custom liquid filter that renders it, but it would look like:

{{ Target.PublishedContent.attachment.Value | attachment_url }}

REST API layer to support headless use of Raytha

This is a non-trivial task, but is essential to build it well for v1.0.0.

For now we have a single API call available to allow developers to ping their application for health check purposes.

image

The initial implementation of the REST API can be a CRUD functionality on:

  • Users [read,write]
  • UserGroups [read,write]
  • Content Items [read,write]
  • Media Items [read,write]
  • Content Types [read only]

These will go a long way to get started and provide immediate value to devs. In later versions we can consider adding CRUD around Templates and other enhancements.

Some big considerations:

  • Authentication method? Most preferred is via API key attached to an admin account. An admin account is assigned to roles with permissions that the API key will inherit.
  • Code needs to be compatible with NSwag to autogenerate swagger API specs and UI

Fix handling of Exception at global level

If there is a 500 error at the content item level, it is handled by the Try-Catch block in the MainController. However, if there is a global 500 error outside of that, it currently redirects the user to the '/error' route. The problem is that there is no page at this route, so the user sees a 404 error instead.

To avoid this confusion, the system administrator can create a content item with a page route of '/error' as a workaround.

But we should fix this internally.

image

New field type: Editor

Discussed in #16

Originally posted by apexdodge December 31, 2022
We currently use the Trix Editor by Basecamp, which is a very effective editor for writing and blogging. However, it lacks advanced features that may be desired by some users. Some of the limitations of the Trix Editor include:

  • Lack of ability to modify the dimensions of image uploads
  • Links cannot be set to open in new tabs
  • No table support
  • Limited options for font, font size, background color, etc.
  • Cannot embed videos

To address these limitations, we propose adding an additional field type called "Editor" or "WYSIWYG" to our system. This field type would include the full suite of features that users expect in an editor, such as the ability to modify image dimensions, create tables, and embed videos. System admins would still have the option to use the Long Text field type, but the Editor field type would provide additional functionality for those who need it.

As a side note, we were previously unaware that the TinyMCE editor is licensed under the MIT license. This could potentially be an alternative option to consider as well.

We are going with TinyMCE since it is the best WYSIWYG with an MIT license.

Will try to implement in a minor release since I do not believe a database migration is required for this implementation.

SAML / JWT login result in not found error if named other than saml or jwt.

These two spots:

var authScheme = db.AuthenticationSchemes.FirstOrDefault(p =>

var authScheme = db.AuthenticationSchemes.FirstOrDefault(p =>

Need to be changed to search by p.DeveloperName, not p.AuthenticationSchemeType.

This got by testing because in testing I named my saml and jwt authentication schemes saml and jwt respectively. In which case it finds it fine. So that is the workaround til this is fixed.

Task:

  • Ensure that the LoginWithSaml and LoginWithJwt properly search by DeveloperName
  • Test with DeveloperNames other than saml and jwt

RedirectPermanent on media item redirect may be problematic

This code below:

return RedirectPermanent(downloadUrl);

I'm thinking it has to be Redirect() instead of RedirectPermanent() because it appears to be cached by cloudflare, the browser, or both. But the url being generated has a 1 day expiry, so if the cache > 24 hrs it redirects to an expired asset.

ref: https://stackoverflow.com/questions/17517318/redirect-vs-redirectpermanent-in-asp-net-mvc

FluidParser should use static variable

Here in our RenderEngine service: https://github.com/RaythaHQ/raytha/blob/main/src/Raytha.Web/Services/RenderEngine.cs

We are instantiating a new FluidParser() every time.

However, according to Fluid's documentation here: https://github.com/sebastienros/fluid#thread-safety, it is Thread Safe and should be shared by the whole application, but the TemplateContext should be instantiated every time.

Task:

  • Confirm we should make this change
  • Change to use private static readonly FluidParser _parser = new FluidParser();
  • Perform tests

EditSmtp.Command and InitialSetup.Command should have IConfiguration

In the InitialSetup.Command() and EditSmtp.Command() application service layer take in MissingSmtpEnvironmentVariables as a property in the input DTO.

This is silly and IConfiguration should be injected into those application service layers. Expecting the Web layer to pass that in does not make much sense.

bool isMissingSmtpEnvVars = string.IsNullOrEmpty(_config["SMTP_HOST"]);

Task:

  • Remove MissingSmtpEnvironmentVariables from the Command Dtos for InitialSetup and EditSmtp actions.

BaseFormSubmit_RenderModel should not interfere with ModelState.IsValid

In creating the /contact form on raytha.com, I wanted to use the out of the box ModelState.IsValid functionality that comes with .NET since it is a common use case.

image

However, in the ModelState.IsValid check at the controller level, the SuccessMessage, RequestVerificationToken, and ValidationFailures attributes threw an error as they were empty.

image

Being empty is expected on a Form Submit.

By setting them to nullable, and { get; set; } instead of { get; init; }, it works.

Notyf not firing on reorder list update.

Drag and drop using the reorder list JS controller does not show a notyf notification of success or failure at the bottom right:

image

For some reason, none of this code is running:

image

However, the update is successfully made on the server.

Improve View's validation to handle bad input

Two tasks here:

  • When layering on a filter in a view's settings, you can input bad input. This will result in a 500 error when instead, it should simply return "invalid value" since the OData parser crashes trying to process it.
  • When trying to sort by bad or malicious values via query string, it results in 500 error, when it should just gracefully fallback to the default view's settings.

Show database storage usage on dashboard

We need another block on the dashboard for Database storage usage.

image

The block should show:

  • Storage consumed
  • Storage allotted
  • Percent used

The storage allotted can be pulled from appsettings.json.

image

The GetDashboardMetrics.Query needs the code for querying the database for its size.

https://github.com/RaythaHQ/raytha/blob/main/src/Raytha.Application/Dashboard/Queries/GetDashboardMetrics.cs

I believe we can make a query with Dappr.

EXEC sp_spaceused @oneresultset = 1

Result:

image

Add Environment Variable to allow for Raytha to run at a different path base

If you want to run Raytha behind a reverse proxy where your domain might be something.com but you want Raytha to run at something.com/mysite, it works remarkably well. I tested it on kubernetes behind nginx ingress.

All you have to do is add this line of code in Startup.cs as the first line in Configure(..)

image

But I think it might a good idea to allow this to be specified in an appsettings.json.

Task:

  • Add in appsettings.json a new app setting: "PATHBASE". If the value is set in appsettings.json, change the PathBase to the one specified, otherwise leave it be.

Include all standard renderable variables in _Layout

Currently the parent layout _Layout does not have any of the Target variables when you click to Insert Variable. Out of convenience for the template author, they should be easily searchable in the Insert Variable menu.

Include all query parameters in the rendered Liquid model.

Add a category in the Insert Variable box to allow the administrator to insert values from the Request query parameters.

image

I believe there are many use cases where the person building the liquid templates will be expecting an arbitrary query parameter, and can use that to their desire.

Similar to how Target.ValidationFailures[...] is a key-value dictionary, we should have something like Request.Query[...] as the usage in the liquid model.

Refactor JsonQueryEngine

One of the most difficult builds of my life, the code is immensely complicated and tightly coupled in certain areas. We will need to refactor this section:

image

However, given the complex nature of it, we will need to complete #10 first to have good test coverage on it before completing the refactoring.

Update nuget and npm packages to latest compatible versions.

Most third party libraries are pretty close to the latest versions but I noticed several that can be updated. There is also a "StringToExpression" library that don't believe is used anymore. Will confirm and remove if so.

On the javascript side, we actually do not have that many dependencies: https://github.com/RaythaHQ/raytha/blob/master/src/Raytha.Web/wwwroot/raytha_admin/js/package.json but we might as well update them too.

Task:

  • Identify packages that can be upgraded
  • Review if there are any breaking changes. Create new issue if there is a breaking change and fix that.
  • Investigate if StringToExpression package is still being used, and remove if necessary.
  • Perform tests.

Add support for Azure Blob Custom domain

Successfully setup azure blob storage behind Cloudflare reverse proxy. Benefits of this is are:

  1. Cached assets / resources which saves on bandwidth
  2. Can make use of Cloudflare image resizer / polish functionality
  3. Consistent branding - assets.raytha.com

The problem is that the current Azure Blob Storage implementation generates SAS urls without the custom domain.

Task:

  • Add another property in appsettings.json: FILE_STORAGE_AZUREBLOB_CUSTOM_DOMAIN
  • If there is a value provided, do a string.Replace() on the hostname of the returned SAS url with the custom domain.
  • See if the URL pattern can be compatible with cloudflare image resizer

Refactor hotwired js controllers.

Some of these controllers need to have their code cleaned up and moved into their own folders. I overloaded the shared directory throughout development. Not a difficult refactoring, just need to be smart about the folder organization and structure.

image

Add a CONTRIBUTING.md file

We need to formalize the CONTRIBUTION information, which should include the following:

  • All contributions must be made under the MIT license.
  • The following branches should be described:
    • main is the current production branch and should be kept in a clean state at all times.
    • release-X.X.X is typically the next release branch. It is frozen in the sense that no new features will be added, but bug fixes and security upgrades that are intended for the next release will be applied to this branch.
    • dev is the branch where new features are developed. For example, a Unit Tests branch may be created from dev, and a REST API branch may also be created from dev. When each of these features is complete, they are merged back into dev. When we have enough new features for the target milestone, a new release-X.X.X branch is created from dev. When we are ready to release, we merge release-X.X.X into main and tag the merge as a new release. After the release, dev should rebase on top of main and continue development.

Support DomainEvents that fire before AND after db.SaveChanges()

This line here:

await _mediator.DispatchDomainEvents(this);

Our default Raytha implementation fires the DomainEvents before items are saved to the database. But there are many use cases where you may want to handle an event that retrieve the item from the db after the changes have saved, and then perform some action.

We can support both by having DomainEvents choose to implement either INotificationBefore or INotificationAfter. The implementations can be empty, but we can use this fire those that chose Before/After respectively.

I think by default, if the developer forgets to choose, we'll default to After db changes are saved.

Liquid filter to convert to Organization Timezone

By default, the liquid template outputs UTC format, but we want to give the Template builder the ability to conveniently convert the time to the same time specified in the system configuration settings.

Example:

<span class="ud-blog-date">{{ item.CreationTime | organization_time: '%b %e %Y, %l:%M:%S %P' }}</span>

The following code needs to be added to https://github.com/RaythaHQ/raytha/blob/main/src/Raytha.Web/Services/RenderEngine.cs

    public static ValueTask<FluidValue> LocalDateFilter(FluidValue input, FilterArguments arguments, TemplateContext context)
    {
        var value = TimeZoneConverter(input, context);
        return ReferenceEquals(value, NilValue.Instance) ? value : MiscFilters.Date(value, arguments, context);
    }

    private static FluidValue TimeZoneConverter(FluidValue input, TemplateContext context)
    {
        if (!input.TryGetDateTimeInput(context, out var value))
        {
            return NilValue.Instance;
        }

        var utc = DateTime.SpecifyKind(value.DateTime, DateTimeKind.Utc);

        // Create new offset for UTC
        var localOffset = new DateTimeOffset(utc, TimeSpan.Zero);

        var result = TimeZoneInfo.ConvertTime(localOffset, context.TimeZone);
        return new DateTimeValue(result);
    }

And:

options.Filters.AddFilter("organization_time", LocalDateFilter);

And we should update the default template too so this filter is in use for fresh installations.

Introduce Monaco Editor for template modification

Right now, modifying the Raytha templates is just raw <textarea> fields but this is not an enjoyable experience. Integration with CodeMirror was not successful in our first iteration.

We will investigate use of Monaco Editor (MIT Open Source) which is the same technology that powers VS Code.

npm install monaco-editor

import * as monaco from 'monaco-editor';

// Initialize the editor
var editor = monaco.editor.create(document.getElementById('editor-container'), {
  value: "function hello() {\n\talert('Hello, world!');\n}",
  language: 'javascript'
});

List view public settings enhancements

In list view > public settings, where we set whether the list view is published and what the route path is, we should add settings for the following functionality:

  • Default number of items per page
  • Max number of items per page
  • Ignore layered filter added by public query params. Meaning, list views published to the public side default to the filter set by the admin, but it is possible for the public user to filter even further (they can only ever do a subset of what the admin allows). However, there may be cases where the admin does not want any ability for the visitor to subset their list.

Update README

Remove (coming soon) from: REST API automatically generated based on content types (coming soon)

Add github action to automatically build and run tests

Since we have made progress on #10, we should consider adding a Github Action that automatically builds and runs the tests when pushed. Then we can get the little badges that says "Builds successful" or "Tests passed"

I like what strapi does: https://github.com/strapi/strapi

  • Do they run on every feature branch or just main / dev / release-vX.X.X ?

main = current production
release-vX.X.X = next minor release (branch off main for minor fixes and minor features)
dev = serves as trunk for major feature branches and PRs. Eventually turns into a release-v.X.X.X branch when ready to roll out a major release.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.