Code Monkey home page Code Monkey logo

framework's Introduction

Dappur PHP Framework

A stylish PHP application framework crafted using Slim, Twig, Eloquent and Sentinel designed to get you from clone to production in a matter of minutes.

Built on the Slim PHP Micro Framework, Twig templating engine, Eloquent ORM database interactions, Phinx database migrations, Sentinel user management, Monolog w/ Logentries Support, form validation with CSRF protection, cookie management, database controlled config,Cloudinary CMS integration, blog, SEO, oauth2 login, and two-factor authentication.

This is a lightweight full featured framework intended for PHP developers who need an open source, fast and reliable platform to build your apps from. Have your new projects up and running in minutes with the provided basic bootstrap pages and basic bootstrap admin.

Important Links

Demo
Documentation
Changelog
dApp CLI

Quick Start Via Vagrant

Once installed, run vagrant up in the project root to provision a box that contains:

- Ubuntu 18
- PHP 7.2
- Composer
- Phinx
- MariaDB 10.3
- Apache 2

The script will also fetch dependencies, create a dev database, and run the initial migration for you. Services will be accessible through:

This framework comes with several pre-made Bootstrap pages to help get your project moving. All of these pages and their respective controllers/views provide you an insight into how the framework functions including form validation, CSRF, working with Eloquent ORM and other plugins. You can expand on the default template or create a completely new template using Twig and the front-end framework of your choosing.

In addition to the few basic front end templates, this framework also comes pre-built with a basic Bootstrap 3 admin dashboard. This dashboard can be accessed automatically by logging in with the admin user credentials.

//TODO

  • Create Documentation
  • Beef up the dApp CLI
  • Add Unit Testing

Pre-Requisites

PHP - PHP is a popular general-purpose scripting language that is especially suited to web development

MySQL Server - MySQL Server, the world's most popular open source database, and MySQL Cluster, a real-time, open source transactional database.

Composer - Dependency manager is required in order to use the Dappur PHP Framework. Installation Instructions

Phinx - Phinx is required in order to utilize the database migrations. It is recommended that you install Phinx globally via composer by running:

$ composer global require robmorgan/phinx

Install with dApp (Experimental)

This command clones your project via the composer create-project command and downloads the themes as well as prepare your settings.json file.

$ dapp new new_app

Install Via Composer

Step 1 (Create the project)

You can start a new project user the Composer create-project command.

$ composer create-project dappur/framework new_app

Step 2 (Install the themes)

If you install via composer, you will have to install both of the themes manually. Simply copy the theme folder from the theme repository into you app/views folder inside your project. If you are using a custom theme, you will have to change the initial migration to support that theme before you migrate your database.

Step 3 (Prepare settings.json file)

Inside the root of your project, you will need to copy the settings.json.dist to settings.json.

$ cp settings.json.dist settings.json

Once copied, open settings.json and change the "framework" name to your project name. You can also set up any other options as well as your database credentials.

Initial Database Migration

If you are not using Vagrant, you have one more step to go before you are live. You will need to ensure that you database credentials are correct in settings.json and then run the following command in a terminal from your root project directory:

$ phinx migrate

Run & Test Project

If you've chosen to use vagrant, you can simply visit the configured URL:PORT after completing the vagrant up command. Otherwise, once you have successfully done the initial migration, you can simply use PHP's built in web server to test your application by running the following from your root project directory:

$ php -S localhost:8181 -t public

Navigate to http://localhost:8181 to view your project.

Default Admin Username: admin
Default Admin Password: admin123

It is HIGHLY recommended that you change the password immediately after your initial migration.

Created Using

  • Slim - Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs
  • Slim Twig-View - Slim Framework 3 view helper built on top of the Twig 2 templating component
  • Slim Flash Messaging - Slim Framework Flash message service provider
  • Slim CSRF - Slim Framework 3 CSRF protection middleware
  • Slim Validation - A validator for Slim micro-framework using Respect\Validation
  • Cartalyst Sentinel - PHP 5.4+ Fully-featured Authentication & Authorization System
  • Illuminate Database - The Illuminate Database component is a full database toolkit for PHP, providing an expressive query builder, ActiveRecord style ORM, and schema builder.
  • Monolog Logging - Send logs to files, sockets, inboxes, databases and various web services.
  • Fig Cookies - Cookies for PSR-7 HTTP Message Interface.
  • Phinx Database Migrations - Phinx makes it ridiculously easy to manage the database migrations for your PHP app.
  • Cloudinary Image CDN - Cloudinary is a cloud service that offers a solution to a web application's entire image management pipeline.
  • PHPMailer - A full-featured email creation and transfer class for PHP.
  • Paginator - A lightweight PHP paginator, for generating pagination controls in the style of Stack Overflow and Flickr.
  • UUID - A PHP library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).
  • Jobby - Manage all your cron jobs without modifying crontab. Handles locking, logging, error emails, and more.
  • TwoFactorAuth - PHP library for Two Factor Authentication (TFA / 2FA)

framework's People

Contributors

beyley avatar dshimkoski avatar edwardteach42 avatar reiz 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

framework's Issues

CSRF For Ajax

Create a route for ajax scripts to get CSRF tokens for post requests.

HTML Config Item

Make an HTML Config item that opens a WYSIWYG window to enter HTML code.

utf8mb4

Why use in the database utf8? utf8mb4 modern encoding. Supports Emoji storage in text fields.
Thanks!

500: Application Error : Admin Dashboard : Solution ?

First of all, thank you for this project.
I test and i learn and i have an
"Error 500 ..... Unable to find template "dashboard.twig" (looked into: ../app/views/dappur). "
Yes, of course this file is in "../app/views/dashboard"...

My solution :
In file app/bootstrap/dependencies.php, line 91, i changed this :

if (substr($container['request']->getUri()->getPath(), 0, 10 ) === "dashboard") {

into this

if (strpos($container['request']->getUri()->getPath(), 'dashboard' ) !== false) {

I hope this will help.
Cordially,

500 Error Oauth2 users

Been following this project for a while now - update to OAuth and getting following error

/opt/sites/dappur-test/vendor/slim/slim/Slim/CallableResolver.php
Line: 104
Message: [{},"oauth2Users"] is not resolvable...

Also in the providers all providers are saying even though they are set in the file

Client ID and/or Client Secret not found. Facebook might not work until these are added to the settings.json file.

Thanks and keep up the work :)

Initial migration failed

Migration failed on
Filed 'last_login' doesn't have a default value while creating the default admin user.

Made it work by changing in the XXX_init_database.php file:
$table->timestamp('last_login');
to
$table->timestamp('last_login')->nullable();
or
$table->timestamp('last_login')->useCurrent();

New version with Slim4?

Hello!

Your project is very interesting!

Do you plan to grow it till Slim4?

Thanks for keeping the project demo site.
I am trying to learn how to push working together Slim4 and Sentinel. Unsuccessfully for a while ...

I am confusing "\Slim\Middleware\Session" in your code because I cannot find such middleware in Slim3/4 :)

ANNOUNCEMENT: v4.0 Coming Soon

I have been busy with several other projects recently and havent had much time to devote to this. I am in the process of finishing up a v4.0 release which cleans up some dappurware as well as some bug fixes. If you have any requests for other features before I finish this up, now is the time to do so!

Add user error 500

Somewhere That Works

Error: Call to a member function get() on null in /var/www/html/new_app/app/src/Controller/AdminUsers.php:139 Stack trace: #0 [internal function]: Dappur\Controller\AdminUsers->usersAdd(Object(Slim\Http\Request), Object(Slim\Http\Response)) #1 /var/www/html/new_app/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php(40): call_user_func_array(Array, Array) #2 /var/www/html/new_app/vendor/slim/slim/Slim/Route.php(344): Slim\Handlers\Strategies\RequestResponseArgs->__invoke(Array, Object(Slim\Http\Request), Object(Slim\Http\Response), Array) #3 /var/www/html/new_app/app/src/Middleware/Auth.php(12): Slim\Route->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response)) #4 [internal function]: Dappur\Middleware\Auth->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Slim\Route)) #5 /var/www/html/new_app/vendor/slim/slim/Slim/DeferredCallable.php(43): call_user_func_array(Object(Dappur\Middleware\Auth), Array) #6 [internal function]: Slim\DeferredCallable->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Slim\Route)) #7 /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(73): call_user_func(Object(Slim\DeferredCallable), Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Slim\Route)) #8 /var/www/html/new_app/app/src/Middleware/Admin.php(12): Slim\Route->Slim\{closure}(Object(Slim\Http\Request), Object(Slim\Http\Response)) #9 [internal function]: Dappur\Middleware\Admin->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Closure)) #10 /var/www/html/new_app/vendor/slim/slim/Slim/DeferredCallable.php(43): call_user_func_array(Object(Dappur\Middleware\Admin), Array) #11 [internal function]: Slim\DeferredCallable->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Closure)) #12 /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(73): call_user_func(Object(Slim\DeferredCallable), Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Closure)) #13 /var/www/html/new_app/vendor/slim/csrf/src/Guard.php(167): Slim\Route->Slim\{closure}(Object(Slim\Http\Request), Object(Slim\Http\Response)) #14 [internal function]: Slim\Csrf\Guard->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Closure)) #15 /var/www/html/new_app/vendor/slim/slim/Slim/DeferredCallable.php(43): call_user_func_array(Object(Slim\Csrf\Guard), Array) #16 [internal function]: Slim\DeferredCallable->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Closure)) #17 /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(73): call_user_func(Object(Slim\DeferredCallable), Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Closure)) #18 /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(122): Slim\Route->Slim\{closure}(Object(Slim\Http\Request), Object(Slim\Http\Response)) #19 /var/www/html/new_app/vendor/slim/slim/Slim/Route.php(316): Slim\Route->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response)) #20 /var/www/html/new_app/vendor/slim/slim/Slim/App.php(476): Slim\Route->run(Object(Slim\Http\Request), Object(Slim\Http\Response)) #21 /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(122): Slim\App->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response)) #22 /var/www/html/new_app/vendor/slim/slim/Slim/App.php(370): Slim\App->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response)) #23 /var/www/html/new_app/vendor/slim/slim/Slim/App.php(295): Slim\App->process(Object(Slim\Http\Request), Object(Slim\Http\Response)) #24 /var/www/html/new_app/public/index.php(30): Slim\App->run() #25 {main}
Call to a member function get() on null

Function: usersAdd
Class: Dappur\Controller\AdminUsers
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php
Line: 40
Function: call_user_func_array
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/Route.php
Line: 344
Function: __invoke
Class: Slim\Handlers\Strategies\RequestResponseArgs
Type: ->
Args: Array
File: /var/www/html/new_app/app/src/Middleware/Auth.php
Line: 12
Function: __invoke
Class: Slim\Route
Type: ->
Args: Array
Function: __invoke
Class: Dappur\Middleware\Auth
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/DeferredCallable.php
Line: 43
Function: call_user_func_array
Args: Array
Function: __invoke
Class: Slim\DeferredCallable
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php
Line: 73
Function: call_user_func
Args: Array
File: /var/www/html/new_app/app/src/Middleware/Admin.php
Line: 12
Function: Slim\{closure}
Class: Slim\Route
Type: ->
Args: Array
Function: __invoke
Class: Dappur\Middleware\Admin
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/DeferredCallable.php
Line: 43
Function: call_user_func_array
Args: Array
Function: __invoke
Class: Slim\DeferredCallable
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php
Line: 73
Function: call_user_func
Args: Array
File: /var/www/html/new_app/vendor/slim/csrf/src/Guard.php
Line: 167
Function: Slim\{closure}
Class: Slim\Route
Type: ->
Args: Array
Function: __invoke
Class: Slim\Csrf\Guard
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/DeferredCallable.php
Line: 43
Function: call_user_func_array
Args: Array
Function: __invoke
Class: Slim\DeferredCallable
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php
Line: 73
Function: call_user_func
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php
Line: 122
Function: Slim\{closure}
Class: Slim\Route
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/Route.php
Line: 316
Function: callMiddlewareStack
Class: Slim\Route
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/App.php
Line: 476
Function: run
Class: Slim\Route
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/MiddlewareAwareTrait.php
Line: 122
Function: __invoke
Class: Slim\App
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/App.php
Line: 370
Function: callMiddlewareStack
Class: Slim\App
Type: ->
Args: Array
File: /var/www/html/new_app/vendor/slim/slim/Slim/App.php
Line: 295
Function: process
Class: Slim\App
Type: ->
Args: Array
File: /var/www/html/new_app/public/index.php
Line: 30
Function: run
Class: Slim\App
Type: ->
Args: Array

first_name:Wender
last_name:Teixeira
email:[email protected]
username:teste
password:teste123
password_confirm:teste123
roles[]:auditor
perm_name[]:User
perm_value[]:true
perm_name[]:Developer
perm_value[]:true
dappurcsrf_name:dappurcsrf59b9fe3369aa6
dappurcsrf_value:1dc4a8b058d1320b89c6c6758381a7f2a4a7fe229f20f7929c9eeb17279ced7c
user_id:

Add environment support to phinx.php

Add environmental support to phinx.php for migrations. This was migrations can be handled either manually from command line or automatically from the deployment script.

Too long text in page content causes 500 error

As the title says, putting too much text in the "page content" section causes the admin panel to 500 error out and page text not being set

The error put out is this

/vagrant/vendor/illuminate/database/Connection.php

Line: 664

Message: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'content' at row 1 (SQL: update `routes` set `content` =`some really long text`, `updated_at` = 2019-07-10 12:17:17 where `id` = 1)

I managed to fix this problem by setting the column content in the routes table to LONGTEXT instead of TEXT

Cron: Call to a member function connection() on null

        $myClass = new myClass();

        $jobby = new \Jobby\Jobby();

        // Sample Job
        $jobby->add('SampleCron', [
            'closure' => function () use (&$myClass) {

                echo Carbon::now();
                echo PHP_EOL;

                $myClass->code = 'test_imp1';
                $myClass->name = 'Test import';
                $myClass->description = 'Test import';
                $myClass->state = 1;

                $myClass->save();

                return true;
            },
            'schedule' => '* * * * *',
            'output'   => __DIR__ . '/../../../storage/log/cron/sample.log',
            'enabled' => true
        ]);

        $jobby->run();

Output:

[2019-03-05 09:36:33] ERROR: Closure did not return true! Returned:
Call to a member function connection() on null

Is there a way to perform some database operation with cron job?

initial migration error

Hi) at the initial migration i get an error. try local server (windows 10) and ubuntu server.
`27087@ALEX777 d:\CloudOjavu\OpenServer526\domains\dappur1.ru
$ C:/Users/27087/AppData/Roaming/Composer/vendor/bin/phinx.bat migrate
Phinx by CakePHP - https://phinx.org. 0.10.6

using config file .\phinx.php
using config parser php
using migration paths

  • D:\CloudOjavu\OpenServer526\domains\dappur1.ru\database\migrations
    warning no environment specified, defaulting to: development
    using adapter mysql
    using database dappur1

== 20170118012924 InitDatabase: migrating
== 20170118012924 InitDatabase: migrated 1.7090s

== 20180216163853 AddSeoOptions: migrating
== 20180216163853 AddSeoOptions: migrated 0.0621s

== 20180222064705 AddOauth: migrating
== 20180222064705 AddOauth: migrated 0.1807s

== 20180717054011 AdminLteConfig: migrating
== 20180717054011 AdminLteConfig: migrated 0.0022s

== 20180722001608 AddTwoFactorAuth: migrating
== 20180722001608 AddTwoFactorAuth: migrated 0.0676s

== 20180722211504 AddCustomPages: migrating
== 20180722211504 AddCustomPages: migrated 0.1373s

== 20180728191437 AddMenuEditor: migrating

In Connection.php line 664:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use ne
ar 'json null, created_at timestamp null, updated_at timestamp null) default cha' at line 1 (SQL: create table menus (id int unsigned not null auto_increment primary key, name v
archar(255) not null, json json null, created_at timestamp null, updated_at timestamp null) default character set utf8 collate 'utf8_unicode_ci')

In Connection.php line 452:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use ne
ar 'json null, created_at timestamp null, updated_at timestamp null) default cha' at line 1

migrate [-c|--configuration CONFIGURATION] [-p|--parser PARSER] [-e|--environment ENVIRONMENT] [-t|--target TARGET] [-d|--date DATE] [-x|--dry-run] [--fake]

                                                                                                                                                                                            `

What should I do? Thank)

Issue with Interop\Container\ContainerInterface

Hi,

I am getting all sorts of issues when setting the project up from scratch. I tried to create this as a Vagrant file, and the PHPmyadmin worked, but I got an 403 forbidden for the frontend.
So I switched to setting up it without Vagrant and ended up with issues like the below:

Fatal error: Uncaught TypeError: Argument 1 passed to Dappur\Middleware\Middleware::__construct() must be an instance of Interop\Container\ContainerInterface, instance of Slim\Container given, called in /app/routes/admin-blog.php on line 98 and defined in /app/src/Middleware/Middleware.php:27 Stack trace: #0 /app/routes/admin-blog.php(98): Dappur\Middleware\Middleware->__construct(Object(Slim\Container)) #1 /vendor/slim/slim/Slim/RouteGroup.php(25): Closure->{closure}(Object(Slim\App)) #2 /vendor/slim/slim/Slim/App.php(272): Slim\RouteGroup->__invoke(Object(Slim\App)) #3 /app/routes/admin-blog.php(99): Slim\Ap in /app/src/Middleware/Middleware.php on line 27

Something doesn't seem right?

error session in php 7.2

in php 7.2 error warning:
run on windows 7 php 7.2

Warning: session_set_cookie_params(): Cannot change session cookie parameters when session is active in D:\WWW_PROJECT\PROJECT\framework\public\index.php on line 3

and 

Fatal error: Uncaught RuntimeException: Unexpected data in output buffer. Maybe you have characters before an opening <?php tag? in D:\WWW_PROJECT\PROJECT\framework\vendor\slim\slim\Slim\App.php:604 Stack trace: #0 D:\WWW_PROJECT\PROJECT\framework\vendor\slim\slim\Slim\App.php(316): Slim\App->finalize(Object(Slim\Http\Response)) #1 D:\WWW_PROJECT\PROJECT\framework\public\index.php(30): Slim\App->run() #2 {main} thrown in D:\WWW_PROJECT\PROJECT\framework\vendor\slim\slim\Slim\App.php on line 604

eloquent model observer

Hello)) help me please))
i use Redis Symfony\Component\Cache\Adapter\RedisAdapter
i added in dependencies.php

$container['cache'] = function ($c) {
    $config = [
        'schema' => 'tcp',
        'host' => 'localhost',
        'port' => 6379,
            // other options
    ];
    $connection = new Predis\Client($config);
    return new Symfony\Component\Cache\Adapter\RedisAdapter($connection);
};

next
i added in dependencies.php

Dappur\Model\Room::observe(new Dappur\Model\Observers\RoomObserver($container));
Dappur\Model\RoomVideo::observe(new Dappur\Model\Observers\RoomVideoObserver($container));
Dappur\Model\RoomUser::observe(new Dappur\Model\Observers\RoomUserObserver($container));

i want use Redis in the Observer events

and i have

Line: 918

Message: Target [Interop\Container\ContainerInterface] is not instantiable while building [Dappur\Model\Observers\RoomUserObserver].

what i do no right? thank you

Anything in users about box causes 500

/srv/users/serverpilot/apps/0-default/vendor/illuminate/database/Connection.php

Line: 664

Message: SQLSTATE[HY000]: General error: 1364 Field 'about' doesn't have a default value (SQL: insert into `users_profile` (`user_id`, `updated_at`, `created_at`) values (41, 2019-07-16 10:55:41, 2019-07-16 10:55:41))

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.