Nano - PHP7, MVC, PDO

Status
Not open for further replies.

BIOS

ಠ‿ಠ
Apr 25, 2012
906
247
4kbfweb.png

Nano is a lightweight, clean & fast Content Management System (CMS) which follows the MVC architecure and is based on a modern, stable and extensible base.​

Features:
  • Secure - Prepared statements, validated data & sanitized output, CSRF protection (A secure token is generated and restricted, can only be used for the form which it was generated for & only valid for one use), Bot/brute-force protection (A user can only attempt to login once every so interval otherwise a short suspension will be given which isn't really recognizable to legitimate users but will have a big impact on bots, also uses Google reCaptcha for registration and such), secure password hashing, protection for session-based attacks, click-jacking protection, plus other useful basic measures.
  • Native language system - No requests to external services, all major site content can be modified on a per language level.
  • Session manager - A very simple and clean wrapper to interact with session data.
  • Extensions - Easily add extensions to the CMS and utilize functionality on either a global scale or per request.
  • Themes - Multiple theme support, all functionality will be available regardless of theme in-use as this logic is separated and maintained.
  • Advanced logging - Extremely useful logging, error/warning/notice stack traces will be logged to a local file and the user will be displayed a friendly message.
  • Events - Trigger & fire user defined callback events, useful for things like proxy/ban checking.
Completed:
  • Base functionality - Routing, user system, language system, error/success flash messages + more.
  • Articles - Toggle categories, likes, responses.
  • Mail integration - Can be used to send account activation/forgot password e-mails to users.
  • Logging system - Can be used to log errors/warnings of the CMS or even log misc information such as attack attempts or visits to certain pages containing useful information of the request such as user agent, IP, time, etc.
  • Various pages - A number of pages have been implemented such as me, account settings, articles, staff and client.

PHP:
/**
* [authenticate is a function to validate user credentials]
* @param  string $username [The username to attempt]
* @param  string $password [The password to attempt]
* @return bool             [Whether or not the combination was correct]
*/
    public function authenticate(string $username, string $password): bool {

        if($this->usernameTaken($username)){

            $hash = $this->engine->fetch("SELECT password FROM users WHERE username = ?", array($username))->password;

            if($this->secure->basicVerify($password, $hash)){

                return true;

            }else{

                $this->session->increment('security', 'attempts');
                $this->session->set('time', time(), 'security');
                return false;

            }

        }else{

            return false;

        }

    }

/**
* [usernameTaken is a function to check if a username is in-use]
* @param  string $username [The username to check]
* @return bool             [Whether or not the username is in-use]
*/
    public function usernameTaken(string $username): bool {

        $checkUsername = $this->engine->fetch("SELECT null FROM users WHERE username = ?", array($username));

        if($checkUsername){

            return true;

        }else{

            return false;

        }

/**
* [getStaff is a function to get the list of staff members]
* @return array [All staff ranks and their respective members]
*/
public function getStaff(){

    $ranks = \Flight::engine()->fetchAll(
        "SELECT
            r.id, r.name
        FROM
            ranks r
        CROSS JOIN
            site_permissions p
        WHERE
            p.permission = ?
        AND
            r.id >= p.min_rank
        ORDER BY
            r.id
        DESC",
        array('display_staff')
    );

    $rank = [];
    foreach($ranks as $r){

        $staff = \Flight::engine()->fetchAll("SELECT id, username, motto, look, online FROM users WHERE rank = ?", array($r->id));
        $rank[$r->name] = $staff;

    }
    return $rank;

}
Index Controller:
PHP:
namespace Acme\Controllers;

use Library\Extensions\{IndexUserMessage, Ext};

class IndexController extends Controller {

    public function __construct(){

        parent::__construct();
        self::$event->register('checkBan');
        self::$event->fire();

    }

    public static function show(){

        if(!self::$user->active()){

            return \Flight::view()->display('index.tpl', [
             'error' => self::$session->getFlash('error'),
             'success' => self::$session->getFlash('success'),
             'form_token_login' => self::$secure->macGenerate('/'),
             'locale' => self::$locale->get('index')
            ]);

        }else{
            \Flight::redirect('me');
            exit();
        }

    }

}
yOfmwXV.png

FaAFhxl.png

pYwmwO7.jpg

Libraries currently in use: Mailgun, Twig, Flight, and Monolog.

Credits:
Geo - Developer
@Brought & @Sex - Moral support
@cammex - Cammex theme (Default theme I used to develop alongside Nano)
 
Last edited:

Brought

更加努力
Jan 14, 2013
593
203
I'm very happy you chose to make this thread! I am also super excited for this to be completed. You've worked hard and I know that it's not something you work on too frequently bc of college but it has come along very nicely.
 

Jaden

not so active
Aug 24, 2014
886
263
Looking forward to seeing more of this, GitHub would be appreciated as well.
 

BIOS

ಠ‿ಠ
Apr 25, 2012
906
247
Recently there hasn't been a lot of development for this, reason being I have been focusing on my final assignments of the year which Brought has previously mentioned, you can most likely expect more frequent updates in the coming weeks.

That said, there are a few updates that I will share on the developments:
Slla9oA.gif

J1LOiGp.png

YXSKRW1.png

Keep in mind that these are still being worked on heavily, therefore they are not final.
 
Last edited:

Synt4x

Member
Jan 13, 2016
77
59
The PHP looks good, would like to see some more snippets regarding the main classes but from what I can see it looks to be well coded. I'm not a big fan of the theme though, but I like the concepts that it has to offer.

Good luck with the project and I hope it does well.
 

BIOS

ಠ‿ಠ
Apr 25, 2012
906
247
The PHP looks good, would like to see some more snippets regarding the main classes but from what I can see it looks to be well coded. I'm not a big fan of the theme though, but I like the concepts that it has to offer.

Good luck with the project and I hope it does well.
Thanks for the feedback, also I did make a start on another lighter theme a while back so there will be more options to choose from.

Database:
PHP:
/**
* [initiate is a function to initiate a database connection]
* @return object [Returns the PDO database instance]
*/
        public function initiate(){

            if($this->db instanceof PDO){
                return $this->db;
            }

        }

/**
* [query is a function to query the database]
* @param  string $query [The SQL query to execute]
* @param  array  $bind  [The array of bound parameters]
*/
        public function query(string $query, array $bind = []){

            try{

                $this->stmt = $this->db->prepare($query);
                $this->stmt->execute($bind);

            }catch(PDOException $e){

                $this->logger->addWarning("SQL error: ".$e);
                exit('Sorry, something happened. Please try again.');

            }

        }

User:
PHP:
/**
* [create is a function to create a new user]
* @param  string $username [The desired username]
* @param  string $mail     [The desired e-mail]
* @param  string $password [The desired password]
*/
    public function create(string $username, string $mail, string $password){

        $this->engine->query(
            "INSERT INTO
                users
                (
                    username,
                    password,
                    mail,
                    motto,
                    auth_ticket,
                    account_created,
                    last_online,
                    ip_last,
                    ip_reg
                )
            VALUES
                (:username, :password, :mail, :motto, 0, 'now', 0, :lastip, :regip)",
            array(
                ':username' => $username,
                ':password' => $this->secure->basicCreate($password),
                ':mail' => $mail,
                ':motto' => \Flight::settings('game', 'motto'),
                ':regip' => \Flight::request()->ip,
                ':lastip' => \Flight::request()->ip
            )
        );

    }
 
Last edited:

Brought

更加努力
Jan 14, 2013
593
203
By far one of my favorite developments yet. Still eager for this one to get finished.
 

BIOS

ಠ‿ಠ
Apr 25, 2012
906
247
Some updates on the administration area, mostly article related.

Admin articles view:
5pTICpB.gif


yRme7lq.png


Articles view template
:
HTML:
{% if articles %}


<div class="table-responsive">
    <table class="table">
        <thead>
            <tr>
                <th>#</th>
                <th>Title</th>
                <th>Preview</th>
                <th>Slug</th>
                <th>Published</th>
                <th>Author</th>
                <th>Category</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            {% for article in articles %}
                <tr>
                    <td>{{ article.id }}</td>
                    <td>{{ article.title }}</td>
                    <td>{{ article.preview }}</td>
                    <td>{{ article.slug }}</td>
                    <td>{{ article.published }}</td>
                    <td>{{ article.author }}</td>
                    <td>{{ article.category }}</td>
                    <td>


                        <div class="btn-group-vertical">
                            <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
                            Manage <span class="caret"></span>
                            </button>


                            <ul class="dropdown-menu" style="position:relative">
                                {% if article.live == true %}
                                    <li><a href="/admin/articles/withdraw/{{ article.id }}">Withdraw</a></li>
                                {% else %}
                                    <li><a href="/admin/articles/publish/{{ article.id }}">Publish</a></li>
                                {% endif %}
                                <li><a href="/admin/articles/edit/{{ article.id }}">Edit</a></li>
                                <li><a href="/admin/articles/delete/{{ article.id }}">Remove</a></li>
                            </ul>
                        </div>


                    </td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
</div>


{% else %}
    No articles have been published yet, <a href="/admin/articles/compose">compose</a> one?
{% endif %}

Admin article compose view:
9SctRaL.png
 
Status
Not open for further replies.

Users who are viewing this thread

Top