├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── RoboFile.php
├── docker-compose.yaml
├── docker
└── web
│ ├── dockerfile
│ ├── init.sh
│ ├── supervisord-proxy.conf
│ └── vhost.conf
├── docs
├── .gitignore
├── .vuepress
│ ├── config.js
│ └── dist
│ │ ├── 404.html
│ │ ├── assets
│ │ ├── css
│ │ │ └── 0.styles.35bcedcf.css
│ │ ├── img
│ │ │ ├── 0990f53c83bb94a02d8885a973aa6736f1de022081d874f3556ea40ff6abad83.f8b9e053.png
│ │ │ ├── 20014d5f04411184559b7a49ca1300a9b95e867acda5b7942524f035e054a28b.0f836819.png
│ │ │ ├── 38d04db14246b8c3008d303da81563dab3ba4a2db6949d77951f550c23735e6d.d38183b9.png
│ │ │ ├── 42b313a369564f02f6cc7afb400de46e6d08e6d25cf2df0802babdec3263866b.1caaebb8.png
│ │ │ ├── 43bd995595b8e51e9fe3eb9a0bf133e348b01336310e92530319197e9fddd701.d5e94f17.png
│ │ │ ├── 48fa4dbf28e3314719f9b69e246ca7bd9f397f64311a11e799e44524aaf46dee.75964ac4.png
│ │ │ ├── 548d567dbab937cd2c77d9bce2e62132c91df20b2c4f027aa7871136fdf7f2ac.a95fb44a.png
│ │ │ ├── 54fc0a9b336b290c16ebf4375808f1c6a15b8fe7f916073893680fce7077950c.38e22bbb.png
│ │ │ ├── 554aaa554abae4a604986b38b3fbd9900e29aa433448adcb58188a351b3a1ec7.dfacdb2f.png
│ │ │ ├── 5d1e579c1b1b685a759be5201f47a734ee568cc012d068cd18b6b0f533927104.18804581.png
│ │ │ ├── 5d488deee54ed0b05ffdb6fd5f5642e33bbefa4a441bb81c8a072cc681598c8e.1becf902.png
│ │ │ ├── 817daf704b66a572f2c3b163320abbc0508b2dd200f7dfd36ab294f58e0e19e0.e3533ad6.png
│ │ │ ├── 92ade1fe984e3dded00156cbe7920d0de9d243f262b1a03c902583552ac61a03.f94908c0.png
│ │ │ ├── 9a3fe6dce02bd6cc8484f711f949c16e42c35e84d13d4ea0ace536dc7122f750.969bde3b.png
│ │ │ ├── a1cac133c49ff024b2024d1a78d2da451d1e58d3c827651e4dc62090d9e87183.488a5649.png
│ │ │ ├── b217c0402e8f49361a24080b2c91e28f1a24c0b26760aaf89871ac00a0949c9e.01cd5750.png
│ │ │ ├── e5629dd0d0718e6844a29966eaa1be70ff69f6d540b9df73fb512a8455a1faaf.5892a7f7.png
│ │ │ ├── e9789275ff88333a7d004b0d1a2833fa8cc226882ea63b830e39295e1e1b5412.424e7ba4.png
│ │ │ ├── f78cb444544a6985f61463396f626bde993a360412463d1726af53250fe548f4.82c20197.png
│ │ │ ├── f88288b384cfd27d55d410ba9015be1d1b32ed6cf060b46f73dae23f0f497fc4.49898d8d.png
│ │ │ ├── fc8073dcebc631393515945821d4c101d32b80aaea1c399e59c47eeb94ef1b68.ecb0794d.png
│ │ │ ├── fcfe6c149194be94f11e7de6691f6de6e09593fe10f305c7dac2c1a3853251e2.197c7d78.png
│ │ │ ├── ff792949fdb0d8359b1f20a1db6763d23430e8d94b58180f38be1342f8ccce0c.33b19f02.png
│ │ │ └── search.83621669.svg
│ │ └── js
│ │ │ ├── 2.abbacd5f.js
│ │ │ ├── 3.752c41d5.js
│ │ │ ├── 4.5e253ff5.js
│ │ │ ├── 5.f7ea1688.js
│ │ │ ├── 6.a65e5dd2.js
│ │ │ ├── 7.1eab93e4.js
│ │ │ ├── 8.4e522548.js
│ │ │ └── app.216dffaf.js
│ │ ├── index.html
│ │ └── zh
│ │ └── index.html
├── README.md
├── images
│ ├── 0990f53c83bb94a02d8885a973aa6736f1de022081d874f3556ea40ff6abad83.png
│ ├── 20014d5f04411184559b7a49ca1300a9b95e867acda5b7942524f035e054a28b.png
│ ├── 38d04db14246b8c3008d303da81563dab3ba4a2db6949d77951f550c23735e6d.png
│ ├── 42b313a369564f02f6cc7afb400de46e6d08e6d25cf2df0802babdec3263866b.png
│ ├── 43bd995595b8e51e9fe3eb9a0bf133e348b01336310e92530319197e9fddd701.png
│ ├── 48fa4dbf28e3314719f9b69e246ca7bd9f397f64311a11e799e44524aaf46dee.png
│ ├── 548d567dbab937cd2c77d9bce2e62132c91df20b2c4f027aa7871136fdf7f2ac.png
│ ├── 54fc0a9b336b290c16ebf4375808f1c6a15b8fe7f916073893680fce7077950c.png
│ ├── 554aaa554abae4a604986b38b3fbd9900e29aa433448adcb58188a351b3a1ec7.png
│ ├── 5d1e579c1b1b685a759be5201f47a734ee568cc012d068cd18b6b0f533927104.png
│ ├── 5d488deee54ed0b05ffdb6fd5f5642e33bbefa4a441bb81c8a072cc681598c8e.png
│ ├── 817daf704b66a572f2c3b163320abbc0508b2dd200f7dfd36ab294f58e0e19e0.png
│ ├── 92ade1fe984e3dded00156cbe7920d0de9d243f262b1a03c902583552ac61a03.png
│ ├── 9a3fe6dce02bd6cc8484f711f949c16e42c35e84d13d4ea0ace536dc7122f750.png
│ ├── a1cac133c49ff024b2024d1a78d2da451d1e58d3c827651e4dc62090d9e87183.png
│ ├── ac6800e6f4dddef7b963b6c14346a46e0183c63186d5ed90de979f7958968105.png
│ ├── b217c0402e8f49361a24080b2c91e28f1a24c0b26760aaf89871ac00a0949c9e.png
│ ├── e5629dd0d0718e6844a29966eaa1be70ff69f6d540b9df73fb512a8455a1faaf.png
│ ├── e9789275ff88333a7d004b0d1a2833fa8cc226882ea63b830e39295e1e1b5412.png
│ ├── f78cb444544a6985f61463396f626bde993a360412463d1726af53250fe548f4.png
│ ├── f88288b384cfd27d55d410ba9015be1d1b32ed6cf060b46f73dae23f0f497fc4.png
│ ├── fc8073dcebc631393515945821d4c101d32b80aaea1c399e59c47eeb94ef1b68.png
│ ├── fcfe6c149194be94f11e7de6691f6de6e09593fe10f305c7dac2c1a3853251e2.png
│ └── ff792949fdb0d8359b1f20a1db6763d23430e8d94b58180f38be1342f8ccce0c.png
├── package.json
├── yarn.lock
└── zh
│ └── README.md
├── images
└── 7ff8a6db94c5aa55be336a84bcab53c5c198d33919179a77df37dc7e593b4574.png
├── proxy
├── RoboFile.php
├── go.mod
├── go.sum
├── proxy
│ ├── assets
│ │ ├── rules.json
│ │ └── settings.json
│ ├── proxy.go
│ ├── proxy_test.go
│ └── types.go
├── rules.json
├── server
├── server-linux
├── server-mac
├── server.go
└── settings.json
└── web
├── .editorconfig
├── .env.example
├── .gitattributes
├── .gitignore
├── .styleci.yml
├── README.md
├── app
├── Actions
│ ├── Fortify
│ │ ├── CreateNewUser.php
│ │ ├── PasswordValidationRules.php
│ │ ├── ResetUserPassword.php
│ │ ├── UpdateUserPassword.php
│ │ └── UpdateUserProfileInformation.php
│ └── Jetstream
│ │ └── DeleteUser.php
├── Console
│ ├── Commands
│ │ └── Test.php
│ └── Kernel.php
├── Exceptions
│ └── Handler.php
├── Http
│ ├── Controllers
│ │ ├── ApiController.php
│ │ ├── AssertController.php
│ │ ├── Controller.php
│ │ └── WebhookController.php
│ ├── Kernel.php
│ ├── Livewire
│ │ └── Prism
│ │ │ └── Admin
│ │ │ ├── Content.php
│ │ │ ├── ContentCreate.php
│ │ │ ├── ContentDelete.php
│ │ │ ├── ContentItem.php
│ │ │ ├── ContentModify.php
│ │ │ ├── Links.php
│ │ │ ├── MemberItem.php
│ │ │ ├── Members.php
│ │ │ ├── MembersModify.php
│ │ │ ├── Plan.php
│ │ │ ├── PlanCreate.php
│ │ │ ├── PlanDelete.php
│ │ │ ├── PlanItem.php
│ │ │ ├── PlanModify.php
│ │ │ └── Settings.php
│ ├── Middleware
│ │ ├── Authenticate.php
│ │ ├── CheckAdmin.php
│ │ ├── CheckJwt.php
│ │ ├── EncryptCookies.php
│ │ ├── LoadConfig.php
│ │ ├── PreventRequestsDuringMaintenance.php
│ │ ├── RedirectIfAuthenticated.php
│ │ ├── TrimStrings.php
│ │ ├── TrustHosts.php
│ │ ├── TrustProxies.php
│ │ └── VerifyCsrfToken.php
│ └── helpers.php
├── Models
│ ├── Content.php
│ ├── Payinfo.php
│ ├── Plan.php
│ ├── Settings.php
│ └── User.php
├── Providers
│ ├── AppServiceProvider.php
│ ├── AuthServiceProvider.php
│ ├── BroadcastServiceProvider.php
│ ├── EventServiceProvider.php
│ ├── FortifyServiceProvider.php
│ ├── JetstreamServiceProvider.php
│ └── RouteServiceProvider.php
└── View
│ └── Components
│ ├── AppLayout.php
│ ├── Detail.php
│ ├── GuestLayout.php
│ └── Span.php
├── artisan
├── bootstrap
├── app.php
└── cache
│ └── .gitignore
├── composer.json
├── composer.lock
├── config
├── app.php
├── auth.php
├── broadcasting.php
├── cache.php
├── cors.php
├── database.php
├── filesystems.php
├── fortify.php
├── hashing.php
├── jetstream.php
├── logging.php
├── mail.php
├── queue.php
├── sanctum.php
├── services.php
├── session.php
└── view.php
├── database
├── .gitignore
├── factories
│ └── UserFactory.php
├── migrations
│ ├── 2014_10_12_000000_create_users_table.php
│ ├── 2014_10_12_100000_create_password_resets_table.php
│ ├── 2014_10_12_200000_add_two_factor_columns_to_users_table.php
│ ├── 2019_05_03_000001_create_customer_columns.php
│ ├── 2019_05_03_000002_create_subscriptions_table.php
│ ├── 2019_05_03_000003_create_subscription_items_table.php
│ ├── 2019_08_19_000000_create_failed_jobs_table.php
│ ├── 2019_12_14_000001_create_personal_access_tokens_table.php
│ ├── 2021_02_19_084258_create_sessions_table.php
│ ├── 2021_02_19_090050_add_level_to_users_tables.php
│ ├── 2021_02_20_065353_create_content_table.php
│ ├── 2021_02_20_091827_create_plans_table.php
│ ├── 2021_02_20_092033_create_content_to_plans_table.php
│ ├── 2021_02_22_045143_add_subscription_info_to_users_table.php
│ ├── 2021_02_22_045431_create_payinfo_table.php
│ └── 2021_02_23_101504_create_settings_table.php
└── seeders
│ └── DatabaseSeeder.php
├── package-lock.json
├── package.json
├── phpunit.xml
├── public
├── .htaccess
├── css
│ └── app.css
├── favicon.ico
├── img
│ ├── brand.svg
│ └── logo.svg
├── index.php
├── js
│ └── app.js
├── mix-manifest.json
├── robots.txt
├── site
│ ├── app.css
│ └── app.js
└── web.config
├── resources
├── css
│ └── app.css
├── js
│ ├── app.js
│ └── bootstrap.js
├── lang
│ └── en
│ │ ├── auth.php
│ │ ├── pagination.php
│ │ ├── passwords.php
│ │ └── validation.php
├── markdown
│ ├── policy.md
│ └── terms.md
├── site
│ ├── .gitignore
│ ├── dist
│ │ ├── app.css
│ │ └── app.js
│ ├── headcode.html
│ ├── mix-manifest.json
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ ├── alpine.min.js
│ │ ├── app.js
│ │ ├── app.scss
│ │ └── app2.scss
│ ├── webpack.mix.js
│ └── yarn.lock
└── views
│ ├── admin
│ ├── content
│ │ ├── create.blade.php
│ │ ├── list.blade.php
│ │ └── modify.blade.php
│ ├── links.blade.php
│ ├── members
│ │ ├── list.blade.php
│ │ └── modify.blade.php
│ ├── plans
│ │ ├── create.blade.php
│ │ ├── list.blade.php
│ │ └── modify.blade.php
│ └── settings.blade.php
│ ├── api
│ ├── api-token-manager.blade.php
│ └── index.blade.php
│ ├── auth
│ ├── confirm-password.blade.php
│ ├── forgot-password.blade.php
│ ├── login.blade.php
│ ├── register.blade.php
│ ├── reset-password.blade.php
│ ├── two-factor-challenge.blade.php
│ └── verify-email.blade.php
│ ├── components
│ ├── detail.blade.php
│ └── span.blade.php
│ ├── dashboard.blade.php
│ ├── layouts
│ ├── app.blade.php
│ └── guest.blade.php
│ ├── livewire
│ └── prism
│ │ └── admin
│ │ ├── content-create.blade.php
│ │ ├── content-delete.blade.php
│ │ ├── content-item.blade.php
│ │ ├── content-modify.blade.php
│ │ ├── content.blade.php
│ │ ├── links.blade.php
│ │ ├── member-item.blade.php
│ │ ├── members-modify.blade.php
│ │ ├── members.blade.php
│ │ ├── plan-create.blade.php
│ │ ├── plan-delete.blade.php
│ │ ├── plan-item.blade.php
│ │ ├── plan-modify.blade.php
│ │ ├── plan.blade.php
│ │ └── settings.blade.php
│ ├── navigation-menu.blade.php
│ ├── page
│ ├── profile.blade.php
│ ├── profile2.blade.php
│ ├── user.blade.php
│ └── user2.blade.php
│ ├── policy.blade.php
│ ├── profile
│ ├── delete-user-form.blade.php
│ ├── logout-other-browser-sessions-form.blade.php
│ ├── show.blade.php
│ ├── two-factor-authentication-form.blade.php
│ ├── update-password-form.blade.php
│ └── update-profile-information-form.blade.php
│ ├── terms.blade.php
│ ├── vendor
│ └── jetstream
│ │ ├── components
│ │ ├── action-message.blade.php
│ │ ├── action-section.blade.php
│ │ ├── application-logo.blade.php
│ │ ├── application-mark.blade.php
│ │ ├── authentication-card-logo.blade.php
│ │ ├── authentication-card.blade.php
│ │ ├── banner.blade.php
│ │ ├── button.blade.php
│ │ ├── checkbox.blade.php
│ │ ├── confirmation-modal.blade.php
│ │ ├── confirms-password.blade.php
│ │ ├── danger-button.blade.php
│ │ ├── dialog-modal.blade.php
│ │ ├── dropdown-link.blade.php
│ │ ├── dropdown.blade.php
│ │ ├── form-section.blade.php
│ │ ├── input-error.blade.php
│ │ ├── input.blade.php
│ │ ├── label.blade.php
│ │ ├── modal.blade.php
│ │ ├── nav-link.blade.php
│ │ ├── responsive-nav-link.blade.php
│ │ ├── secondary-button.blade.php
│ │ ├── section-border.blade.php
│ │ ├── section-title.blade.php
│ │ ├── switchable-team.blade.php
│ │ ├── validation-errors.blade.php
│ │ └── welcome.blade.php
│ │ └── mail
│ │ └── team-invitation.blade.php
│ └── welcome.blade.php
├── routes
├── api.php
├── channels.php
├── console.php
└── web.php
├── server.php
├── storage
├── app
│ ├── .gitignore
│ └── public
│ │ └── .gitignore
├── framework
│ ├── .gitignore
│ ├── cache
│ │ ├── .gitignore
│ │ └── data
│ │ │ └── .gitignore
│ ├── sessions
│ │ └── .gitignore
│ ├── testing
│ │ └── .gitignore
│ └── views
│ │ └── .gitignore
└── logs
│ └── .gitignore
├── tailwind.config.js
├── tests
├── CreatesApplication.php
├── Feature
│ ├── ApiTokenPermissionsTest.php
│ ├── AuthenticationTest.php
│ ├── BrowserSessionsTest.php
│ ├── CreateApiTokenTest.php
│ ├── DeleteAccountTest.php
│ ├── DeleteApiTokenTest.php
│ ├── EmailVerificationTest.php
│ ├── ExampleTest.php
│ ├── PasswordConfirmationTest.php
│ ├── PasswordResetTest.php
│ ├── ProfileInformationTest.php
│ ├── RegistrationTest.php
│ ├── TwoFactorAuthenticationSettingsTest.php
│ └── UpdatePasswordTest.php
├── TestCase.php
└── Unit
│ └── ExampleTest.php
└── webpack.mix.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /site
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "git.ignoreLimitWarning": true
3 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This project uses the GPLv2 License with conditions.
2 |
3 | Both individuals and commercial companies can use MemberPrism to build their own member-only content application under the GPLv2 license.
4 |
5 | However, selling MemberPrism itself as a Cloud Hosting service (e.g., Selling MemberPrism as a cloud service through Docker2SaaS or other platforms) is prohibited.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Member Prism
2 |
3 |
4 |
5 | open source alternative to memberstack / memberspace , but with both front and backend member-only content protection
6 |
7 | # Video
8 |
9 | Youtube: How to add membership management, subscriptions and content protection to a website in less than ten minutes.
10 |
11 | [](https://www.youtube.com/watch?v=lmhISws3UJk)
12 |
13 | Bilibili link:
14 |
15 |
16 | # Document
17 |
18 | - [English](docs/README.md)
19 | - [简体中文](docs/zh/README.md)
20 |
21 | # License
22 |
23 | This project uses the GPLv2 License with conditions.
24 |
25 | Both individuals and commercial companies can use MemberPrism to build their own member-only content application under the GPLv2 license.
26 |
27 | However, selling MemberPrism itself as a Cloud Hosting service (e.g., Selling MemberPrism as a cloud service through Docker2SaaS or other platforms) is prohibited.
28 |
--------------------------------------------------------------------------------
/RoboFile.php:
--------------------------------------------------------------------------------
1 | _exec("git add . && git commit -m '$note' && git push");
14 | $tmp_dir = '/tmp/MPT'.md5($repo);
15 | if( file_exists( $tmp_dir ) )
16 | {
17 | $this->_exec("cd $tmp_dir && git pull");
18 | }
19 | else
20 | {
21 | $this->_exec("git clone $repo $tmp_dir");
22 | }
23 | $this->_exec("cd $tmp_dir && cp -rf ./* /Users/Easy/Code/gitcode/MemberPrism2/ && cp -rf ./.vscode /Users/Easy/Code/gitcode/MemberPrism2/ && cp -rf ./.vscode /Users/Easy/Code/gitcode/MemberPrism2/ && cd /Users/Easy/Code/gitcode/MemberPrism2/ && git add . && git commit -m '$note' && git push");
24 |
25 | }
26 | }
--------------------------------------------------------------------------------
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | mariadb:
4 | image: 'mariadb:10.5.8-focal'
5 | volumes:
6 | - 'mariadb_data:/var/lib/mysql'
7 | environment:
8 | - MYSQL_ROOT_PASSWORD=theVeryp@ssw0rd
9 | - MYSQL_DATABASE=prism
10 | ports:
11 | - '3306:3306'
12 | app:
13 | #image: 'webdevops/php-apache:8.0-alpine'
14 | build: './docker/web/'
15 | ports:
16 | - '8801:80'
17 | - '8802:8802'
18 | - '443:443'
19 | volumes:
20 | - './:/app'
21 | depends_on:
22 | - mariadb
23 | environment:
24 | - DB_HOST=mariadb
25 | - DB_PORT=3306
26 | - DB_USERNAME=root
27 | - DB_DATABASE=prism
28 | - DB_PASSWORD=theVeryp@ssw0rd
29 | volumes:
30 | mariadb_data:
--------------------------------------------------------------------------------
/docker/web/dockerfile:
--------------------------------------------------------------------------------
1 | FROM webdevops/php-apache:8.0-alpine
2 |
3 | # 首先配置 vhost
4 | COPY vhost.conf /opt/docker/etc/httpd/vhost.conf
5 | # COPY web.vhost.conf /opt/docker/etc/httpd/vhost.common.d/
6 |
7 | # 然后运行初始化脚本
8 | # https://dockerfile.readthedocs.io/en/latest/content/Customization/provisioning.html
9 | COPY init.sh /opt/docker/provision/entrypoint.d/
10 | #CMD chmod +x /opt/docker/provision/entrypoint.d/init.sh
11 | ADD supervisord-proxy.conf /opt/docker/etc/supervisor.d/prism-proxy.conf
12 |
13 | EXPOSE 80
14 | EXPOSE 8802
15 |
16 |
--------------------------------------------------------------------------------
/docker/web/init.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # 初始化 laravel
4 | cd /app/web && composer install && cp .env.example .env && php artisan key:generate && php artisan migrate --seed
5 |
6 | chmod -R 0777 /app/web/storage
7 | chmod -R 0777 /app/web/bootstrap/cache/
8 |
9 | chmod -R 0777 /app/proxy/
10 | chmod +x /app/proxy/server-linux
11 |
12 | # 启动 proxy
13 | # 已经设置为 deamon
14 | # cd /app/proxy && ./server-linux &
--------------------------------------------------------------------------------
/docker/web/supervisord-proxy.conf:
--------------------------------------------------------------------------------
1 | [group:prism-proxy]
2 | programs=prism-proxy
3 | priority=20
4 |
5 | [program:prism-proxy]
6 | process_name=%(program_name)s
7 | command=/bin/bash -c 'cd /app/proxy/ && ./server-linux'
8 | autostart=true
9 | startretries=10
10 | autorestart=true
11 | priority=1
12 | redirect_stderr=true
13 | stdout_logfile=/proxy.log
--------------------------------------------------------------------------------
/docker/web/vhost.conf:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Vhost
3 | #######################################
4 |
5 |
6 | ServerName docker.vm
7 | ServerAlias *.vm
8 | DocumentRoot "/app/web/public"
9 |
10 | Options FollowSymLinks MultiViews
11 | AllowOverride All
12 | Order allow,deny
13 | allow from all
14 |
15 |
16 |
17 |
18 | ServerName docker.vm
19 | ServerAlias *.vm
20 | DocumentRoot "/app/web/public"
21 |
22 | Options FollowSymLinks MultiViews
23 | AllowOverride All
24 | Order allow,deny
25 | allow from all
26 |
27 | #SSLEngine on
28 | #SSLCertificateFile /app/ssl/server.crt
29 | #SSLCertificateKeyFile /app/ssl/server.key
30 |
31 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | locales: {
3 | '/': {
4 | lang: 'en-US', // 将会被设置为 的 lang 属性
5 | title: 'MemberPrism',
6 | description: 'Open source alternative to memberstack / memberspace , but with both front and backend member-only content protection'
7 | },
8 | '/zh/': {
9 | lang: 'zh-CN',
10 | title: 'MemberPrism',
11 | description: '类似 memberstack 或 memberspace 的开源实现,但对会员内容同时提供了前端和后端的双重保护'
12 | }
13 | },
14 | themeConfig: {
15 | sidebar:'auto',
16 | nav: [
17 | { text: 'Home', link: '/' },
18 | { text: 'GitHub', link: 'https://github.com/easychen/member-prism' },
19 | ]
20 | }
21 | }
--------------------------------------------------------------------------------
/docs/.vuepress/dist/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MemberPrism
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/0990f53c83bb94a02d8885a973aa6736f1de022081d874f3556ea40ff6abad83.f8b9e053.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/0990f53c83bb94a02d8885a973aa6736f1de022081d874f3556ea40ff6abad83.f8b9e053.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/20014d5f04411184559b7a49ca1300a9b95e867acda5b7942524f035e054a28b.0f836819.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/20014d5f04411184559b7a49ca1300a9b95e867acda5b7942524f035e054a28b.0f836819.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/38d04db14246b8c3008d303da81563dab3ba4a2db6949d77951f550c23735e6d.d38183b9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/38d04db14246b8c3008d303da81563dab3ba4a2db6949d77951f550c23735e6d.d38183b9.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/42b313a369564f02f6cc7afb400de46e6d08e6d25cf2df0802babdec3263866b.1caaebb8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/42b313a369564f02f6cc7afb400de46e6d08e6d25cf2df0802babdec3263866b.1caaebb8.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/43bd995595b8e51e9fe3eb9a0bf133e348b01336310e92530319197e9fddd701.d5e94f17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/43bd995595b8e51e9fe3eb9a0bf133e348b01336310e92530319197e9fddd701.d5e94f17.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/48fa4dbf28e3314719f9b69e246ca7bd9f397f64311a11e799e44524aaf46dee.75964ac4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/48fa4dbf28e3314719f9b69e246ca7bd9f397f64311a11e799e44524aaf46dee.75964ac4.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/548d567dbab937cd2c77d9bce2e62132c91df20b2c4f027aa7871136fdf7f2ac.a95fb44a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/548d567dbab937cd2c77d9bce2e62132c91df20b2c4f027aa7871136fdf7f2ac.a95fb44a.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/54fc0a9b336b290c16ebf4375808f1c6a15b8fe7f916073893680fce7077950c.38e22bbb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/54fc0a9b336b290c16ebf4375808f1c6a15b8fe7f916073893680fce7077950c.38e22bbb.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/554aaa554abae4a604986b38b3fbd9900e29aa433448adcb58188a351b3a1ec7.dfacdb2f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/554aaa554abae4a604986b38b3fbd9900e29aa433448adcb58188a351b3a1ec7.dfacdb2f.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/5d1e579c1b1b685a759be5201f47a734ee568cc012d068cd18b6b0f533927104.18804581.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/5d1e579c1b1b685a759be5201f47a734ee568cc012d068cd18b6b0f533927104.18804581.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/5d488deee54ed0b05ffdb6fd5f5642e33bbefa4a441bb81c8a072cc681598c8e.1becf902.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/5d488deee54ed0b05ffdb6fd5f5642e33bbefa4a441bb81c8a072cc681598c8e.1becf902.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/817daf704b66a572f2c3b163320abbc0508b2dd200f7dfd36ab294f58e0e19e0.e3533ad6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/817daf704b66a572f2c3b163320abbc0508b2dd200f7dfd36ab294f58e0e19e0.e3533ad6.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/92ade1fe984e3dded00156cbe7920d0de9d243f262b1a03c902583552ac61a03.f94908c0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/92ade1fe984e3dded00156cbe7920d0de9d243f262b1a03c902583552ac61a03.f94908c0.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/9a3fe6dce02bd6cc8484f711f949c16e42c35e84d13d4ea0ace536dc7122f750.969bde3b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/9a3fe6dce02bd6cc8484f711f949c16e42c35e84d13d4ea0ace536dc7122f750.969bde3b.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/a1cac133c49ff024b2024d1a78d2da451d1e58d3c827651e4dc62090d9e87183.488a5649.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/a1cac133c49ff024b2024d1a78d2da451d1e58d3c827651e4dc62090d9e87183.488a5649.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/b217c0402e8f49361a24080b2c91e28f1a24c0b26760aaf89871ac00a0949c9e.01cd5750.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/b217c0402e8f49361a24080b2c91e28f1a24c0b26760aaf89871ac00a0949c9e.01cd5750.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/e5629dd0d0718e6844a29966eaa1be70ff69f6d540b9df73fb512a8455a1faaf.5892a7f7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/e5629dd0d0718e6844a29966eaa1be70ff69f6d540b9df73fb512a8455a1faaf.5892a7f7.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/e9789275ff88333a7d004b0d1a2833fa8cc226882ea63b830e39295e1e1b5412.424e7ba4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/e9789275ff88333a7d004b0d1a2833fa8cc226882ea63b830e39295e1e1b5412.424e7ba4.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/f78cb444544a6985f61463396f626bde993a360412463d1726af53250fe548f4.82c20197.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/f78cb444544a6985f61463396f626bde993a360412463d1726af53250fe548f4.82c20197.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/f88288b384cfd27d55d410ba9015be1d1b32ed6cf060b46f73dae23f0f497fc4.49898d8d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/f88288b384cfd27d55d410ba9015be1d1b32ed6cf060b46f73dae23f0f497fc4.49898d8d.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/fc8073dcebc631393515945821d4c101d32b80aaea1c399e59c47eeb94ef1b68.ecb0794d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/fc8073dcebc631393515945821d4c101d32b80aaea1c399e59c47eeb94ef1b68.ecb0794d.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/fcfe6c149194be94f11e7de6691f6de6e09593fe10f305c7dac2c1a3853251e2.197c7d78.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/fcfe6c149194be94f11e7de6691f6de6e09593fe10f305c7dac2c1a3853251e2.197c7d78.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/ff792949fdb0d8359b1f20a1db6763d23430e8d94b58180f38be1342f8ccce0c.33b19f02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/.vuepress/dist/assets/img/ff792949fdb0d8359b1f20a1db6763d23430e8d94b58180f38be1342f8ccce0c.33b19f02.png
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/img/search.83621669.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/js/5.f7ea1688.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[5],{359:function(t,e,n){},388:function(t,e,n){"use strict";n(359)},397:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(388),n(40)),p=Object(r.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=p.exports}}]);
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/js/6.a65e5dd2.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[6],{361:function(t,e,a){},390:function(t,e,a){"use strict";a(361)},394:function(t,e,a){"use strict";a.r(e);var n={name:"CodeBlock",props:{title:{type:String,required:!0},active:{type:Boolean,default:!1}},mounted:function(){this.$parent&&this.$parent.loadTabs&&this.$parent.loadTabs()}},i=(a(390),a(40)),s=Object(i.a)(n,(function(){var t=this.$createElement;return(this._self._c||t)("div",{staticClass:"theme-code-block",class:{"theme-code-block__active":this.active}},[this._t("default")],2)}),[],!1,null,"759a7d02",null);e.default=s.exports}}]);
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/js/7.1eab93e4.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[7],{360:function(e,t,a){},389:function(e,t,a){"use strict";a(360)},393:function(e,t,a){"use strict";a.r(t);a(63),a(27),a(94),a(95);var o={name:"CodeGroup",data:function(){return{codeTabs:[],activeCodeTabIndex:-1}},watch:{activeCodeTabIndex:function(e){this.activateCodeTab(e)}},mounted:function(){this.loadTabs()},methods:{changeCodeTab:function(e){this.activeCodeTabIndex=e},loadTabs:function(){var e=this;this.codeTabs=(this.$slots.default||[]).filter((function(e){return Boolean(e.componentOptions)})).map((function(t,a){return""===t.componentOptions.propsData.active&&(e.activeCodeTabIndex=a),{title:t.componentOptions.propsData.title,elm:t.elm}})),-1===this.activeCodeTabIndex&&this.codeTabs.length>0&&(this.activeCodeTabIndex=0),this.activateCodeTab(0)},activateCodeTab:function(e){this.codeTabs.forEach((function(e){e.elm&&e.elm.classList.remove("theme-code-block__active")})),this.codeTabs[e].elm&&this.codeTabs[e].elm.classList.add("theme-code-block__active")}}},n=(a(389),a(40)),c=Object(n.a)(o,(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ClientOnly",[a("div",{staticClass:"theme-code-group"},[a("div",{staticClass:"theme-code-group__nav"},[a("ul",{staticClass:"theme-code-group__ul"},e._l(e.codeTabs,(function(t,o){return a("li",{key:t.title,staticClass:"theme-code-group__li"},[a("button",{staticClass:"theme-code-group__nav-tab",class:{"theme-code-group__nav-tab-active":o===e.activeCodeTabIndex},on:{click:function(t){return e.changeCodeTab(o)}}},[e._v("\n "+e._s(t.title)+"\n ")])])})),0)]),e._v(" "),e._t("default"),e._v(" "),e.codeTabs.length<1?a("pre",{staticClass:"pre-blank"},[e._v("// Make sure to add code blocks to your code group")]):e._e()],2)])}),[],!1,null,"deefee04",null);t.default=c.exports}}]);
--------------------------------------------------------------------------------
/docs/.vuepress/dist/assets/js/8.4e522548.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[8],{392:function(t,e,s){"use strict";s.r(e);var n=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],o={methods:{getMsg:function(){return n[Math.floor(Math.random()*n.length)]}}},i=s(40),h=Object(i.a)(o,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"theme-container"},[e("div",{staticClass:"theme-default-content"},[e("h1",[this._v("404")]),this._v(" "),e("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),e("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])}),[],!1,null,null,null);e.default=h.exports}}]);
--------------------------------------------------------------------------------
/docs/images/0990f53c83bb94a02d8885a973aa6736f1de022081d874f3556ea40ff6abad83.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/0990f53c83bb94a02d8885a973aa6736f1de022081d874f3556ea40ff6abad83.png
--------------------------------------------------------------------------------
/docs/images/20014d5f04411184559b7a49ca1300a9b95e867acda5b7942524f035e054a28b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/20014d5f04411184559b7a49ca1300a9b95e867acda5b7942524f035e054a28b.png
--------------------------------------------------------------------------------
/docs/images/38d04db14246b8c3008d303da81563dab3ba4a2db6949d77951f550c23735e6d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/38d04db14246b8c3008d303da81563dab3ba4a2db6949d77951f550c23735e6d.png
--------------------------------------------------------------------------------
/docs/images/42b313a369564f02f6cc7afb400de46e6d08e6d25cf2df0802babdec3263866b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/42b313a369564f02f6cc7afb400de46e6d08e6d25cf2df0802babdec3263866b.png
--------------------------------------------------------------------------------
/docs/images/43bd995595b8e51e9fe3eb9a0bf133e348b01336310e92530319197e9fddd701.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/43bd995595b8e51e9fe3eb9a0bf133e348b01336310e92530319197e9fddd701.png
--------------------------------------------------------------------------------
/docs/images/48fa4dbf28e3314719f9b69e246ca7bd9f397f64311a11e799e44524aaf46dee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/48fa4dbf28e3314719f9b69e246ca7bd9f397f64311a11e799e44524aaf46dee.png
--------------------------------------------------------------------------------
/docs/images/548d567dbab937cd2c77d9bce2e62132c91df20b2c4f027aa7871136fdf7f2ac.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/548d567dbab937cd2c77d9bce2e62132c91df20b2c4f027aa7871136fdf7f2ac.png
--------------------------------------------------------------------------------
/docs/images/54fc0a9b336b290c16ebf4375808f1c6a15b8fe7f916073893680fce7077950c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/54fc0a9b336b290c16ebf4375808f1c6a15b8fe7f916073893680fce7077950c.png
--------------------------------------------------------------------------------
/docs/images/554aaa554abae4a604986b38b3fbd9900e29aa433448adcb58188a351b3a1ec7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/554aaa554abae4a604986b38b3fbd9900e29aa433448adcb58188a351b3a1ec7.png
--------------------------------------------------------------------------------
/docs/images/5d1e579c1b1b685a759be5201f47a734ee568cc012d068cd18b6b0f533927104.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/5d1e579c1b1b685a759be5201f47a734ee568cc012d068cd18b6b0f533927104.png
--------------------------------------------------------------------------------
/docs/images/5d488deee54ed0b05ffdb6fd5f5642e33bbefa4a441bb81c8a072cc681598c8e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/5d488deee54ed0b05ffdb6fd5f5642e33bbefa4a441bb81c8a072cc681598c8e.png
--------------------------------------------------------------------------------
/docs/images/817daf704b66a572f2c3b163320abbc0508b2dd200f7dfd36ab294f58e0e19e0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/817daf704b66a572f2c3b163320abbc0508b2dd200f7dfd36ab294f58e0e19e0.png
--------------------------------------------------------------------------------
/docs/images/92ade1fe984e3dded00156cbe7920d0de9d243f262b1a03c902583552ac61a03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/92ade1fe984e3dded00156cbe7920d0de9d243f262b1a03c902583552ac61a03.png
--------------------------------------------------------------------------------
/docs/images/9a3fe6dce02bd6cc8484f711f949c16e42c35e84d13d4ea0ace536dc7122f750.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/9a3fe6dce02bd6cc8484f711f949c16e42c35e84d13d4ea0ace536dc7122f750.png
--------------------------------------------------------------------------------
/docs/images/a1cac133c49ff024b2024d1a78d2da451d1e58d3c827651e4dc62090d9e87183.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/a1cac133c49ff024b2024d1a78d2da451d1e58d3c827651e4dc62090d9e87183.png
--------------------------------------------------------------------------------
/docs/images/ac6800e6f4dddef7b963b6c14346a46e0183c63186d5ed90de979f7958968105.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/ac6800e6f4dddef7b963b6c14346a46e0183c63186d5ed90de979f7958968105.png
--------------------------------------------------------------------------------
/docs/images/b217c0402e8f49361a24080b2c91e28f1a24c0b26760aaf89871ac00a0949c9e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/b217c0402e8f49361a24080b2c91e28f1a24c0b26760aaf89871ac00a0949c9e.png
--------------------------------------------------------------------------------
/docs/images/e5629dd0d0718e6844a29966eaa1be70ff69f6d540b9df73fb512a8455a1faaf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/e5629dd0d0718e6844a29966eaa1be70ff69f6d540b9df73fb512a8455a1faaf.png
--------------------------------------------------------------------------------
/docs/images/e9789275ff88333a7d004b0d1a2833fa8cc226882ea63b830e39295e1e1b5412.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/e9789275ff88333a7d004b0d1a2833fa8cc226882ea63b830e39295e1e1b5412.png
--------------------------------------------------------------------------------
/docs/images/f78cb444544a6985f61463396f626bde993a360412463d1726af53250fe548f4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/f78cb444544a6985f61463396f626bde993a360412463d1726af53250fe548f4.png
--------------------------------------------------------------------------------
/docs/images/f88288b384cfd27d55d410ba9015be1d1b32ed6cf060b46f73dae23f0f497fc4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/f88288b384cfd27d55d410ba9015be1d1b32ed6cf060b46f73dae23f0f497fc4.png
--------------------------------------------------------------------------------
/docs/images/fc8073dcebc631393515945821d4c101d32b80aaea1c399e59c47eeb94ef1b68.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/fc8073dcebc631393515945821d4c101d32b80aaea1c399e59c47eeb94ef1b68.png
--------------------------------------------------------------------------------
/docs/images/fcfe6c149194be94f11e7de6691f6de6e09593fe10f305c7dac2c1a3853251e2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/fcfe6c149194be94f11e7de6691f6de6e09593fe10f305c7dac2c1a3853251e2.png
--------------------------------------------------------------------------------
/docs/images/ff792949fdb0d8359b1f20a1db6763d23430e8d94b58180f38be1342f8ccce0c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/docs/images/ff792949fdb0d8359b1f20a1db6763d23430e8d94b58180f38be1342f8ccce0c.png
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docs",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "devDependencies": {
7 | "vuepress": "^1.8.2"
8 | },
9 | "scripts": {
10 | "docs:dev": "vuepress dev ./",
11 | "docs:build": "vuepress build ./"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/images/7ff8a6db94c5aa55be336a84bcab53c5c198d33919179a77df37dc7e593b4574.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/images/7ff8a6db94c5aa55be336a84bcab53c5c198d33919179a77df37dc7e593b4574.png
--------------------------------------------------------------------------------
/proxy/RoboFile.php:
--------------------------------------------------------------------------------
1 | _exec("GOOS=linux GOARCH=amd64 go build -o server-linux server.go ");
13 | $this->_exec("GOOS=darwin GOARCH=amd64 go build -o server-mac server.go");
14 | $this->_exec("cp -f server-linux /Users/Easy/Playground/prism2/proxy/server-linux");
15 | }
16 | }
--------------------------------------------------------------------------------
/proxy/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/easychen/mirror
2 |
3 | go 1.15
4 |
5 | require (
6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible
7 | github.com/fsnotify/fsnotify v1.4.9
8 | github.com/gin-gonic/gin v1.6.3
9 | github.com/go-playground/assert/v2 v2.0.1
10 | github.com/spf13/viper v1.7.1
11 | )
12 |
--------------------------------------------------------------------------------
/proxy/proxy/assets/rules.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": {
3 | "content_id": "1",
4 | "path": "/vip1",
5 | "match": 1,
6 | "redir": "/forbidden.html"
7 | },
8 | "2": {
9 | "content_id": "2",
10 | "path": "/vip2",
11 | "match": 1,
12 | "redir": "/forbidden.html"
13 | },
14 | "3": {
15 | "content_id": "3",
16 | "path": "/vip3",
17 | "match": 1,
18 | "redir": "/forbidden.html"
19 | },
20 | "4": {
21 | "content_id": "4",
22 | "path": "/vip3",
23 | "match": 1,
24 | "redir": "/forbidden.html"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/proxy/proxy/assets/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug": false,
3 | "secret": "hello-im-secret",
4 | "target": "http://127.0.0.1:9000",
5 | "host": "127.0.0.1",
6 | "port": 10086,
7 | "https": false,
8 | "key": "server.key",
9 | "crt": "server.crt"
10 | }
11 |
--------------------------------------------------------------------------------
/proxy/proxy/types.go:
--------------------------------------------------------------------------------
1 | package proxy
2 |
3 | import (
4 | "net/http/httputil"
5 |
6 | "github.com/dgrijalva/jwt-go"
7 | )
8 |
9 | // Proxy 代理
10 | type Proxy struct {
11 | httputil.ReverseProxy
12 | }
13 |
14 | // Settings 配置文件
15 | type Settings struct {
16 | Debug *bool `json:"debug,omitempty"` // 调试模式
17 | Secret string `json:"secret"`
18 | Target string `json:"target"`
19 | Host string `json:"host"` // 服务监听地址
20 | Port int `json:"int"` // 服务地址
21 | HTTPSEnable bool `json:"https_enable"` // HTTPS 证书KEY文件
22 | Key string `json:"key,omitempty"` // HTTPS 证书KEY文件
23 | Crt string `json:"crt,omitempty"` // HTTPS 证书文件
24 | }
25 |
26 | // Rule 规则配置
27 | type Rule struct {
28 | ContentID string `json:"content_id"`
29 | Path string `json:"path"`
30 | Match int `json:"match"`
31 | Redir string `json:"redir"`
32 | }
33 |
34 | // Rules 规则配置
35 | type Rules map[string]Rule
36 |
37 | // Claims JWTClaims
38 | type Claims struct {
39 | ContentIDs []string `json:"content_ids"`
40 | Level int `json:"level"`
41 | UID int `json:"uid"`
42 | Expire string `json:"expire"`
43 | jwt.StandardClaims
44 | }
45 |
--------------------------------------------------------------------------------
/proxy/rules.json:
--------------------------------------------------------------------------------
1 | {"1":{"content_id":"1","path":"\/vip","match":1,"redir":"\/forbidden.html"},"2":{"content_id":"2","path":"\/gogog","match":1,"redir":"\/forbidden.html"},"3":{"content_id":"3","path":"\/vip2","match":1,"redir":"\/forbidden.html"}}
--------------------------------------------------------------------------------
/proxy/server:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/proxy/server
--------------------------------------------------------------------------------
/proxy/server-linux:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/proxy/server-linux
--------------------------------------------------------------------------------
/proxy/server-mac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/proxy/server-mac
--------------------------------------------------------------------------------
/proxy/server.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 |
7 | "github.com/easychen/mirror/proxy"
8 | )
9 |
10 | func main() {
11 |
12 | r, settings, rules := proxy.Setup(proxy.ServerRouters)
13 | fmt.Println("Rules:")
14 | for i, rule := range *rules {
15 | fmt.Printf("[%s] %s %s, %d \n", i, rule.Path, rule.Redir, rule.Match)
16 | }
17 |
18 | fmt.Println("Settings:")
19 | fmt.Printf(
20 | "Host: %s:%d > TargetHost: %s, httpsEnable: %v \n",
21 | settings.Host, settings.Port, settings.Target, settings.HTTPSEnable,
22 | )
23 |
24 | // 启动服务
25 | var err error
26 | if settings.HTTPSEnable {
27 | err = r.RunTLS(fmt.Sprintf("%s:%d", settings.Host, settings.Port), settings.Crt, settings.Key)
28 | } else {
29 | err = r.Run(fmt.Sprintf("%s:%d", settings.Host, settings.Port))
30 | }
31 |
32 | if err != nil {
33 | log.Fatal(err)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/proxy/settings.json:
--------------------------------------------------------------------------------
1 | {"debug":false,"secret":"4137hu82RGHFE4854hgh","target":"http:\/\/localhost:8008","host":"0.0.0.0","port":"8802","https":false,"key":"\/app\/ssl\/server.key","crt":"\/app\/ssl\/server.crt"}
--------------------------------------------------------------------------------
/web/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | indent_style = space
8 | indent_size = 4
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
14 | [*.{yml,yaml}]
15 | indent_size = 2
16 |
--------------------------------------------------------------------------------
/web/.env.example:
--------------------------------------------------------------------------------
1 | APP_NAME=MemberPrism
2 | APP_ENV=local
3 | APP_KEY=
4 | APP_DEBUG=true
5 | APP_URL=http://localhost
6 |
7 | # big logo in front page
8 | APP_LOGO_URL=/img/brand.svg
9 | # small icon left top
10 | APP_ICON_URL=/img/logo.svg
11 |
12 | APP_TITLE="Welcome to Member prism!"
13 | APP_DETAIL="MemberPrism brings plug-in membership system and subscription management to the modern Web, which uses both front-end and back-end protection to make your member-only content more secure."
14 |
15 | LOG_CHANNEL=stack
16 | LOG_LEVEL=debug
17 |
18 | DB_CONNECTION=mysql
19 | DB_HOST=mariadb
20 | DB_PORT=3306
21 | DB_DATABASE=prism
22 | DB_USERNAME=root
23 | DB_PASSWORD=theVeryp@ssw0rd
24 |
25 | BROADCAST_DRIVER=log
26 | CACHE_DRIVER=file
27 | QUEUE_CONNECTION=sync
28 | SESSION_DRIVER=database
29 | SESSION_LIFETIME=120
30 |
31 | MEMCACHED_HOST=127.0.0.1
32 |
33 | REDIS_HOST=127.0.0.1
34 | REDIS_PASSWORD=null
35 | REDIS_PORT=6379
36 |
37 | MAIL_MAILER=smtp
38 | MAIL_HOST=mailhog
39 | MAIL_PORT=1025
40 | MAIL_USERNAME=null
41 | MAIL_PASSWORD=null
42 | MAIL_ENCRYPTION=null
43 | MAIL_FROM_ADDRESS=null
44 | MAIL_FROM_NAME="${APP_NAME}"
45 |
46 | AWS_ACCESS_KEY_ID=
47 | AWS_SECRET_ACCESS_KEY=
48 | AWS_DEFAULT_REGION=us-east-1
49 | AWS_BUCKET=
50 |
51 | PUSHER_APP_ID=
52 | PUSHER_APP_KEY=
53 | PUSHER_APP_SECRET=
54 | PUSHER_APP_CLUSTER=mt1
55 |
56 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
57 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
58 |
59 | STRIPE_KEY=your-stripe-key
60 | STRIPE_SECRET=your-stripe-secret
61 |
62 | PRISM_JWT_KEY=just-a-demo-key
63 | # PRISM_TARGET_URL host for user visiting
64 | PRISM_TARGET_URL=
65 | # PRISM_SOURCE_URL host for admin editing
66 | PRISM_SOURCE_URL=http://ftqq.com
67 | # PRISM_PROXY_PORT local proxy service port
68 | PRISM_PROXY_PORT=8802
69 | PRISM_HTTPS=false
70 | PRISM_MEMBER_EXPIRE_DAYS=2
71 |
--------------------------------------------------------------------------------
/web/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.css linguist-vendored
3 | *.scss linguist-vendored
4 | *.js linguist-vendored
5 | CHANGELOG.md export-ignore
6 |
--------------------------------------------------------------------------------
/web/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /**/node_modules
3 | /web/resources/site/node_modules
4 | /public/hot
5 | /public/storage
6 | /storage/*.key
7 | /vendor
8 | .env
9 | .env.local
10 | .env.backup
11 | .phpunit.result.cache
12 | docker-compose.override.yml
13 | Homestead.json
14 | Homestead.yaml
15 | npm-debug.log
16 | yarn-error.log
17 | /storage/settings.json
18 |
--------------------------------------------------------------------------------
/web/.styleci.yml:
--------------------------------------------------------------------------------
1 | php:
2 | preset: laravel
3 | disabled:
4 | - no_unused_imports
5 | finder:
6 | not-name:
7 | - index.php
8 | - server.php
9 | js:
10 | finder:
11 | not-name:
12 | - webpack.mix.js
13 | css: true
14 |
--------------------------------------------------------------------------------
/web/app/Actions/Fortify/CreateNewUser.php:
--------------------------------------------------------------------------------
1 | ['required', 'string', 'max:255'],
25 | 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
26 | 'password' => $this->passwordRules(),
27 | 'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
28 | ])->validate();
29 |
30 | return User::create([
31 | 'name' => $input['name'],
32 | 'email' => $input['email'],
33 | 'password' => Hash::make($input['password']),
34 | ]);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/web/app/Actions/Fortify/PasswordValidationRules.php:
--------------------------------------------------------------------------------
1 | $this->passwordRules(),
24 | ])->validate();
25 |
26 | $user->forceFill([
27 | 'password' => Hash::make($input['password']),
28 | ])->save();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/web/app/Actions/Fortify/UpdateUserPassword.php:
--------------------------------------------------------------------------------
1 | ['required', 'string'],
24 | 'password' => $this->passwordRules(),
25 | ])->after(function ($validator) use ($user, $input) {
26 | if (! isset($input['current_password']) || ! Hash::check($input['current_password'], $user->password)) {
27 | $validator->errors()->add('current_password', __('The provided password does not match your current password.'));
28 | }
29 | })->validateWithBag('updatePassword');
30 |
31 | $user->forceFill([
32 | 'password' => Hash::make($input['password']),
33 | ])->save();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/web/app/Actions/Fortify/UpdateUserProfileInformation.php:
--------------------------------------------------------------------------------
1 | ['required', 'string', 'max:255'],
23 | 'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
24 | 'photo' => ['nullable', 'image', 'max:1024'],
25 | ])->validateWithBag('updateProfileInformation');
26 |
27 | if (isset($input['photo'])) {
28 | $user->updateProfilePhoto($input['photo']);
29 | }
30 |
31 | if ($input['email'] !== $user->email &&
32 | $user instanceof MustVerifyEmail) {
33 | $this->updateVerifiedUser($user, $input);
34 | } else {
35 | $user->forceFill([
36 | 'name' => $input['name'],
37 | 'email' => $input['email'],
38 | ])->save();
39 | }
40 | }
41 |
42 | /**
43 | * Update the given verified user's profile information.
44 | *
45 | * @param mixed $user
46 | * @param array $input
47 | * @return void
48 | */
49 | protected function updateVerifiedUser($user, array $input)
50 | {
51 | $user->forceFill([
52 | 'name' => $input['name'],
53 | 'email' => $input['email'],
54 | 'email_verified_at' => null,
55 | ])->save();
56 |
57 | $user->sendEmailVerificationNotification();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/web/app/Actions/Jetstream/DeleteUser.php:
--------------------------------------------------------------------------------
1 | deleteProfilePhoto();
18 | $user->tokens->each->delete();
19 | $user->delete();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/web/app/Console/Commands/Test.php:
--------------------------------------------------------------------------------
1 | content_ids = [0=>"1"];
45 | $out->uid = 4;
46 | $out->level = 6;
47 | $out->expire = "2021-03-28";
48 |
49 | echo JWT::encode( $out, env('PRISM_JWT_KEY') );
50 | echo "\r\n---------------";
51 |
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/web/app/Console/Kernel.php:
--------------------------------------------------------------------------------
1 | command('inspire')->hourly();
28 | }
29 |
30 | /**
31 | * Register the commands for the application.
32 | *
33 | * @return void
34 | */
35 | protected function commands()
36 | {
37 | $this->load(__DIR__.'/Commands');
38 |
39 | require base_path('routes/console.php');
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/web/app/Exceptions/Handler.php:
--------------------------------------------------------------------------------
1 | reportable(function (Throwable $e) {
37 | //
38 | });
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/web/app/Http/Controllers/Controller.php:
--------------------------------------------------------------------------------
1 | contents = $contents ? $contents->toArray():[];
15 | }
16 |
17 | public function create()
18 | {
19 | return redirect()->route('content.create');
20 | }
21 |
22 | public function render()
23 | {
24 | return view('livewire.prism.admin.content');
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/ContentCreate.php:
--------------------------------------------------------------------------------
1 | 'StartWith',
11 | '2' => 'ExactMatch',
12 | ];
13 |
14 | public $state = [
15 | 'name' => null,
16 | 'url' => null,
17 | 'match' => '1',
18 | 'redirect_url' => null,
19 | ];
20 |
21 | protected $rules = [
22 | 'state.name' => 'required|string',
23 | 'state.url' => 'required|string',
24 | 'state.match' => 'required|integer',
25 | 'state.redirect_url' => 'required|string',
26 | ];
27 |
28 | public function save()
29 | {
30 | $this->validate();
31 | Content::create( $this->state );
32 | $this->emit('saved');
33 | prism_save_rules();
34 | redirect()->route('content.list');
35 | }
36 |
37 |
38 |
39 |
40 | public function render()
41 | {
42 | return view('livewire.prism.admin.content-create');
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/ContentDelete.php:
--------------------------------------------------------------------------------
1 | confirm = true;
15 | }
16 |
17 | public function cancel()
18 | {
19 | $this->confirm = false;
20 | }
21 |
22 | public function delete()
23 | {
24 | Content::where('id',$this->content['id'])->delete();
25 | $this->emit('saved');
26 | redirect()->route('content.list');
27 | }
28 |
29 | public function render()
30 | {
31 | return view('livewire.prism.admin.content-delete');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/ContentItem.php:
--------------------------------------------------------------------------------
1 | content['id'] )->update( ['enabled' => $new_status] );
15 | $this->content['enabled'] = $new_status;
16 |
17 | }
18 |
19 | public function edit()
20 | {
21 | redirect()->route('content.modify',['content'=>$this->content['id']]);
22 | }
23 |
24 | public function render()
25 | {
26 | return view('livewire.prism.admin.content-item');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/ContentModify.php:
--------------------------------------------------------------------------------
1 | 'StartWith',
13 | '2' => 'ExactMatch',
14 | ];
15 |
16 | public function mount()
17 | {
18 | $this->state = $this->content;
19 | }
20 |
21 | protected $rules = [
22 | 'state.name' => 'required|string',
23 | 'state.url' => 'required|string',
24 | 'state.match' => 'required|integer',
25 | 'state.redirect_url' => 'required|string',
26 | ];
27 |
28 | public function save()
29 | {
30 | $vdata = $this->validate();
31 | Content::where('id',$this->content['id'])->update( $vdata['state'] );
32 | $this->emit('saved');
33 | prism_save_rules();
34 | redirect()->route('content.list');
35 | }
36 |
37 | public function render()
38 | {
39 | return view('livewire.prism.admin.content-modify');
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/MemberItem.php:
--------------------------------------------------------------------------------
1 | route('members.modify',['user'=>$this->member['id']]);
15 | }
16 |
17 | public function change( $status )
18 | {
19 | $new_level = $status == 'user' ? 1 : 6;
20 | User::where( 'id' , $this->member['id'] )->update( ['level' => $new_level] );
21 | $this->member['level'] = $new_level;
22 |
23 | }
24 |
25 | public function render()
26 | {
27 | return view('livewire.prism.admin.member-item');
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/Members.php:
--------------------------------------------------------------------------------
1 | members = User::all()->toArray();
14 | }
15 |
16 | public function render()
17 | {
18 | return view('livewire.prism.admin.members');
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/MembersModify.php:
--------------------------------------------------------------------------------
1 | state = $this->user;
17 | }
18 |
19 | protected $rules = [
20 | 'state.name' => 'required|string',
21 | 'state.email' => 'required|email',
22 | 'state.subscription_expire_date' => 'required|date',
23 | ];
24 |
25 | public function save()
26 | {
27 | $vdata = $this->validate();
28 | if( isset($this->state['password']) && strlen($this->state['password']) > 0 )
29 | {
30 | $vdata['state']['password'] = Hash::make( $this->state['password'] );
31 | }
32 |
33 | User::where('id',$this->user['id'])->update( $vdata['state'] );
34 | $this->emit('saved');
35 | redirect()->route('members');
36 | }
37 |
38 | public function render()
39 | {
40 | return view('livewire.prism.admin.members-modify');
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/Plan.php:
--------------------------------------------------------------------------------
1 | plans = $plans ? $plans->toArray():[];
16 | $this->plans = $plans;
17 | }
18 |
19 | public function create()
20 | {
21 | return redirect()->route('plans.create');
22 | }
23 |
24 | public function render()
25 | {
26 | return view('livewire.prism.admin.plan');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/PlanCreate.php:
--------------------------------------------------------------------------------
1 | null,
11 | 'stripe_price_id' => null
12 | ];
13 |
14 | protected $rules = [
15 | 'state.name' => 'required|string',
16 | 'state.stripe_price_id' => 'required|string',
17 | ];
18 |
19 | public function save()
20 | {
21 | $this->validate();
22 | Plan::create( $this->state );
23 | $this->emit('saved');
24 | redirect()->route('plans.list');
25 | }
26 |
27 | public function render()
28 | {
29 | return view('livewire.prism.admin.plan-create');
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/PlanDelete.php:
--------------------------------------------------------------------------------
1 | confirm = true;
15 | }
16 |
17 | public function cancel()
18 | {
19 | $this->confirm = false;
20 | }
21 |
22 | public function delete()
23 | {
24 | if( $this->plan['member_count'] > 0 ) $this->addError('info', 'cannot remove plan which not empty.');
25 | Plan::where('id',$this->plan['id'])->delete();
26 | $this->emit('saved');
27 | redirect()->route('plans.list');
28 | }
29 |
30 |
31 | public function render()
32 | {
33 | return view('livewire.prism.admin.plan-delete');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/PlanItem.php:
--------------------------------------------------------------------------------
1 | contents = $all->toArray();
19 | $this->selected_contents = $this->plan->contents()->pluck('id');
20 | }
21 |
22 | public function toggle_add( $status )
23 | {
24 | $this->add = $status == 'true';
25 | }
26 |
27 | public function save_content()
28 | {
29 | $plan = Plan::find($this->plan['id']);
30 | $plan->contents()->sync( $this->selected_contents );
31 | $new_plan = Plan::find($this->plan['id']);
32 | $this->selected_contents = $new_plan->contents()->pluck('id');
33 | $this->plan = $new_plan;
34 | prism_save_rules();
35 | $this->add = false;
36 | //dd( $this->selected_contents );
37 | }
38 |
39 |
40 | public function enable( $status )
41 | {
42 | $new_status = $status == 1 ? 1 : 0;
43 | Plan::where( 'id' , $this->plan['id'] )->update( ['enabled' => $new_status] );
44 | $this->plan['enabled'] = $new_status;
45 |
46 | }
47 |
48 | public function edit()
49 | {
50 | redirect()->route('plans.modify',['plan'=>$this->plan['id']]);
51 | }
52 |
53 | public function render()
54 | {
55 | return view('livewire.prism.admin.plan-item');
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/web/app/Http/Livewire/Prism/Admin/PlanModify.php:
--------------------------------------------------------------------------------
1 | state = $this->plan;
15 | }
16 |
17 | protected $rules = [
18 | 'state.name' => 'required|string',
19 | 'state.stripe_price_id' => 'required|string'
20 | ];
21 |
22 | public function save()
23 | {
24 | $vdata = $this->validate();
25 | Plan::where('id',$this->plan['id'])->update( $vdata['state'] );
26 | $this->emit('saved');
27 | prism_save_rules();
28 | redirect()->route('plans.list');
29 | }
30 |
31 | public function render()
32 | {
33 | return view('livewire.prism.admin.plan-modify');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/web/app/Http/Middleware/Authenticate.php:
--------------------------------------------------------------------------------
1 | expectsJson()) {
18 | return route('login');
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/web/app/Http/Middleware/CheckAdmin.php:
--------------------------------------------------------------------------------
1 | bearerToken();
20 | if( $jwt && prism_check_jwt( $jwt ) )
21 | {
22 |
23 | }
24 | else
25 | {
26 | return abort(403,'Login first');
27 | }
28 | return $next($request);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/web/app/Http/Middleware/EncryptCookies.php:
--------------------------------------------------------------------------------
1 | check()) {
26 | return redirect(RouteServiceProvider::HOME);
27 | }
28 | }
29 |
30 | return $next($request);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/web/app/Http/Middleware/TrimStrings.php:
--------------------------------------------------------------------------------
1 | allSubdomainsOfApplicationUrl(),
18 | ];
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/web/app/Http/Middleware/TrustProxies.php:
--------------------------------------------------------------------------------
1 | belongsToMany(Content::class,'content_plans','plans_id' , 'content_id');
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/web/app/Models/Settings.php:
--------------------------------------------------------------------------------
1 | 'datetime',
53 | ];
54 |
55 | /**
56 | * The accessors to append to the model's array form.
57 | *
58 | * @var array
59 | */
60 | protected $appends = [
61 | 'profile_photo_url',
62 | ];
63 | }
64 |
--------------------------------------------------------------------------------
/web/app/Providers/AppServiceProvider.php:
--------------------------------------------------------------------------------
1 | 'App\Policies\ModelPolicy',
18 | ];
19 |
20 | /**
21 | * Register any authentication / authorization services.
22 | *
23 | * @return void
24 | */
25 | public function boot()
26 | {
27 | $this->registerPolicies();
28 |
29 | Gate::define('saas-admin', function (User $user) {
30 | return $user->level >= 6; // 第一个注册的成为管理员
31 | });
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/web/app/Providers/BroadcastServiceProvider.php:
--------------------------------------------------------------------------------
1 | [
19 | SendEmailVerificationNotification::class,
20 | ],
21 | ];
22 |
23 | /**
24 | * Register any events for your application.
25 | *
26 | * @return void
27 | */
28 | public function boot()
29 | {
30 | //
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/web/app/Providers/FortifyServiceProvider.php:
--------------------------------------------------------------------------------
1 | by($request->email.$request->ip());
41 | });
42 |
43 | RateLimiter::for('two-factor', function (Request $request) {
44 | return Limit::perMinute(5)->by($request->session()->get('login.id'));
45 | });
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/web/app/Providers/JetstreamServiceProvider.php:
--------------------------------------------------------------------------------
1 | configurePermissions();
29 |
30 | Jetstream::deleteUsersUsing(DeleteUser::class);
31 | }
32 |
33 | /**
34 | * Configure the permissions that are available within the application.
35 | *
36 | * @return void
37 | */
38 | protected function configurePermissions()
39 | {
40 | Jetstream::defaultApiTokenPermissions(['read']);
41 |
42 | Jetstream::permissions([
43 | 'create',
44 | 'read',
45 | 'update',
46 | 'delete',
47 | ]);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/web/app/Providers/RouteServiceProvider.php:
--------------------------------------------------------------------------------
1 | configureRateLimiting();
39 |
40 | $this->routes(function () {
41 | Route::prefix('api')
42 | ->middleware('api')
43 | ->namespace($this->namespace)
44 | ->group(base_path('routes/api.php'));
45 |
46 | Route::middleware('web')
47 | ->namespace($this->namespace)
48 | ->group(base_path('routes/web.php'));
49 | });
50 | }
51 |
52 | /**
53 | * Configure the rate limiters for the application.
54 | *
55 | * @return void
56 | */
57 | protected function configureRateLimiting()
58 | {
59 | RateLimiter::for('api', function (Request $request) {
60 | return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
61 | });
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/web/app/View/Components/AppLayout.php:
--------------------------------------------------------------------------------
1 | content = $content;
22 | $this->color = $color;
23 | $this->bg = $bg;
24 | $this->class = $class;
25 | // dd( $color );
26 | }
27 |
28 | /**
29 | * Get the view / contents that represent the component.
30 | *
31 | * @return \Illuminate\Contracts\View\View|string
32 | */
33 | public function render()
34 | {
35 | return view('components.span');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/web/artisan:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | make(Illuminate\Contracts\Console\Kernel::class);
34 |
35 | $status = $kernel->handle(
36 | $input = new Symfony\Component\Console\Input\ArgvInput,
37 | new Symfony\Component\Console\Output\ConsoleOutput
38 | );
39 |
40 | /*
41 | |--------------------------------------------------------------------------
42 | | Shutdown The Application
43 | |--------------------------------------------------------------------------
44 | |
45 | | Once Artisan has finished running, we will fire off the shutdown events
46 | | so that any final work may be done by the application before we shut
47 | | down the process. This is the last thing to happen to the request.
48 | |
49 | */
50 |
51 | $kernel->terminate($input, $status);
52 |
53 | exit($status);
54 |
--------------------------------------------------------------------------------
/web/bootstrap/app.php:
--------------------------------------------------------------------------------
1 | singleton(
30 | Illuminate\Contracts\Http\Kernel::class,
31 | App\Http\Kernel::class
32 | );
33 |
34 | $app->singleton(
35 | Illuminate\Contracts\Console\Kernel::class,
36 | App\Console\Kernel::class
37 | );
38 |
39 | $app->singleton(
40 | Illuminate\Contracts\Debug\ExceptionHandler::class,
41 | App\Exceptions\Handler::class
42 | );
43 |
44 | /*
45 | |--------------------------------------------------------------------------
46 | | Return The Application
47 | |--------------------------------------------------------------------------
48 | |
49 | | This script returns the application instance. The instance is given to
50 | | the calling script so we can separate the building of the instances
51 | | from the actual running of the application and sending responses.
52 | |
53 | */
54 |
55 | return $app;
56 |
--------------------------------------------------------------------------------
/web/bootstrap/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/web/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "laravel/laravel",
3 | "type": "project",
4 | "description": "The Laravel Framework.",
5 | "keywords": [
6 | "framework",
7 | "laravel"
8 | ],
9 | "license": "MIT",
10 | "require": {
11 | "php": "^7.3|^8.0",
12 | "creativeorange/gravatar": "~1.0",
13 | "fideloper/proxy": "^4.4",
14 | "firebase/php-jwt": "^5.2",
15 | "fruitcake/laravel-cors": "^2.0",
16 | "guzzlehttp/guzzle": "^7.0.1",
17 | "laravel/cashier": "^12.9",
18 | "laravel/framework": "^8.12",
19 | "laravel/jetstream": "^2.2",
20 | "laravel/sanctum": "^2.6",
21 | "laravel/tinker": "^2.5",
22 | "livewire/livewire": "^2.0"
23 | },
24 | "require-dev": {
25 | "facade/ignition": "^2.5",
26 | "fakerphp/faker": "^1.9.1",
27 | "laravel/sail": "^1.0.1",
28 | "mockery/mockery": "^1.4.2",
29 | "nunomaduro/collision": "^5.0",
30 | "phpunit/phpunit": "^9.3.3"
31 | },
32 | "config": {
33 | "optimize-autoloader": true,
34 | "preferred-install": "dist",
35 | "sort-packages": true
36 | },
37 | "extra": {
38 | "laravel": {
39 | "dont-discover": []
40 | }
41 | },
42 | "autoload": {
43 | "psr-4": {
44 | "App\\": "app/",
45 | "Database\\Factories\\": "database/factories/",
46 | "Database\\Seeders\\": "database/seeders/"
47 | },
48 | "files": ["app/Http/helpers.php"]
49 | },
50 | "autoload-dev": {
51 | "psr-4": {
52 | "Tests\\": "tests/"
53 | }
54 | },
55 | "minimum-stability": "dev",
56 | "prefer-stable": true,
57 | "scripts": {
58 | "post-autoload-dump": [
59 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
60 | "@php artisan package:discover --ansi"
61 | ],
62 | "post-root-package-install": [
63 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
64 | ],
65 | "post-create-project-cmd": [
66 | "@php artisan key:generate --ansi"
67 | ]
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/web/config/broadcasting.php:
--------------------------------------------------------------------------------
1 | env('BROADCAST_DRIVER', 'null'),
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Broadcast Connections
23 | |--------------------------------------------------------------------------
24 | |
25 | | Here you may define all of the broadcast connections that will be used
26 | | to broadcast events to other systems or over websockets. Samples of
27 | | each available type of connection are provided inside this array.
28 | |
29 | */
30 |
31 | 'connections' => [
32 |
33 | 'pusher' => [
34 | 'driver' => 'pusher',
35 | 'key' => env('PUSHER_APP_KEY'),
36 | 'secret' => env('PUSHER_APP_SECRET'),
37 | 'app_id' => env('PUSHER_APP_ID'),
38 | 'options' => [
39 | 'cluster' => env('PUSHER_APP_CLUSTER'),
40 | 'useTLS' => true,
41 | ],
42 | ],
43 |
44 | 'ably' => [
45 | 'driver' => 'ably',
46 | 'key' => env('ABLY_KEY'),
47 | ],
48 |
49 | 'redis' => [
50 | 'driver' => 'redis',
51 | 'connection' => 'default',
52 | ],
53 |
54 | 'log' => [
55 | 'driver' => 'log',
56 | ],
57 |
58 | 'null' => [
59 | 'driver' => 'null',
60 | ],
61 |
62 | ],
63 |
64 | ];
65 |
--------------------------------------------------------------------------------
/web/config/cors.php:
--------------------------------------------------------------------------------
1 | ['api/*', 'sanctum/csrf-cookie'],
19 |
20 | 'allowed_methods' => ['*'],
21 |
22 | 'allowed_origins' => ['*'],
23 |
24 | 'allowed_origins_patterns' => [],
25 |
26 | 'allowed_headers' => ['*'],
27 |
28 | 'exposed_headers' => [],
29 |
30 | 'max_age' => 0,
31 |
32 | 'supports_credentials' => false,
33 |
34 | ];
35 |
--------------------------------------------------------------------------------
/web/config/hashing.php:
--------------------------------------------------------------------------------
1 | 'bcrypt',
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Bcrypt Options
23 | |--------------------------------------------------------------------------
24 | |
25 | | Here you may specify the configuration options that should be used when
26 | | passwords are hashed using the Bcrypt algorithm. This will allow you
27 | | to control the amount of time it takes to hash the given password.
28 | |
29 | */
30 |
31 | 'bcrypt' => [
32 | 'rounds' => env('BCRYPT_ROUNDS', 10),
33 | ],
34 |
35 | /*
36 | |--------------------------------------------------------------------------
37 | | Argon Options
38 | |--------------------------------------------------------------------------
39 | |
40 | | Here you may specify the configuration options that should be used when
41 | | passwords are hashed using the Argon algorithm. These will allow you
42 | | to control the amount of time it takes to hash the given password.
43 | |
44 | */
45 |
46 | 'argon' => [
47 | 'memory' => 1024,
48 | 'threads' => 2,
49 | 'time' => 2,
50 | ],
51 |
52 | ];
53 |
--------------------------------------------------------------------------------
/web/config/sanctum.php:
--------------------------------------------------------------------------------
1 | explode(',', env(
17 | 'SANCTUM_STATEFUL_DOMAINS',
18 | 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1'
19 | )),
20 |
21 | /*
22 | |--------------------------------------------------------------------------
23 | | Expiration Minutes
24 | |--------------------------------------------------------------------------
25 | |
26 | | This value controls the number of minutes until an issued token will be
27 | | considered expired. If this value is null, personal access tokens do
28 | | not expire. This won't tweak the lifetime of first-party sessions.
29 | |
30 | */
31 |
32 | 'expiration' => null,
33 |
34 | /*
35 | |--------------------------------------------------------------------------
36 | | Sanctum Middleware
37 | |--------------------------------------------------------------------------
38 | |
39 | | When authenticating your first-party SPA with Sanctum you may need to
40 | | customize some of the middleware Sanctum uses while processing the
41 | | request. You may change the middleware listed below as required.
42 | |
43 | */
44 |
45 | 'middleware' => [
46 | 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
47 | 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
48 | ],
49 |
50 | ];
51 |
--------------------------------------------------------------------------------
/web/config/services.php:
--------------------------------------------------------------------------------
1 | [
18 | 'domain' => env('MAILGUN_DOMAIN'),
19 | 'secret' => env('MAILGUN_SECRET'),
20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
21 | ],
22 |
23 | 'postmark' => [
24 | 'token' => env('POSTMARK_TOKEN'),
25 | ],
26 |
27 | 'ses' => [
28 | 'key' => env('AWS_ACCESS_KEY_ID'),
29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'),
30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
31 | ],
32 |
33 | ];
34 |
--------------------------------------------------------------------------------
/web/config/view.php:
--------------------------------------------------------------------------------
1 | [
17 | resource_path('views'),
18 | ],
19 |
20 | /*
21 | |--------------------------------------------------------------------------
22 | | Compiled View Path
23 | |--------------------------------------------------------------------------
24 | |
25 | | This option determines where all the compiled Blade templates will be
26 | | stored for your application. Typically, this is within the storage
27 | | directory. However, as usual, you are free to change this value.
28 | |
29 | */
30 |
31 | 'compiled' => env(
32 | 'VIEW_COMPILED_PATH',
33 | realpath(storage_path('framework/views'))
34 | ),
35 |
36 | ];
37 |
--------------------------------------------------------------------------------
/web/database/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite
2 | *.sqlite-journal
3 |
--------------------------------------------------------------------------------
/web/database/factories/UserFactory.php:
--------------------------------------------------------------------------------
1 | $this->faker->name,
27 | 'email' => $this->faker->unique()->safeEmail,
28 | 'email_verified_at' => now(),
29 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
30 | 'remember_token' => Str::random(10),
31 | ];
32 | }
33 |
34 | /**
35 | * Indicate that the model's email address should be unverified.
36 | *
37 | * @return \Illuminate\Database\Eloquent\Factories\Factory
38 | */
39 | public function unverified()
40 | {
41 | return $this->state(function (array $attributes) {
42 | return [
43 | 'email_verified_at' => null,
44 | ];
45 | });
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/web/database/migrations/2014_10_12_000000_create_users_table.php:
--------------------------------------------------------------------------------
1 | id();
18 | $table->string('name');
19 | $table->string('email')->unique();
20 | $table->timestamp('email_verified_at')->nullable();
21 | $table->string('password');
22 | $table->rememberToken();
23 | $table->foreignId('current_team_id')->nullable();
24 | $table->text('profile_photo_path')->nullable();
25 | $table->timestamps();
26 | });
27 | }
28 |
29 | /**
30 | * Reverse the migrations.
31 | *
32 | * @return void
33 | */
34 | public function down()
35 | {
36 | Schema::dropIfExists('users');
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/web/database/migrations/2014_10_12_100000_create_password_resets_table.php:
--------------------------------------------------------------------------------
1 | string('email')->index();
18 | $table->string('token');
19 | $table->timestamp('created_at')->nullable();
20 | });
21 | }
22 |
23 | /**
24 | * Reverse the migrations.
25 | *
26 | * @return void
27 | */
28 | public function down()
29 | {
30 | Schema::dropIfExists('password_resets');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/web/database/migrations/2014_10_12_200000_add_two_factor_columns_to_users_table.php:
--------------------------------------------------------------------------------
1 | text('two_factor_secret')
18 | ->after('password')
19 | ->nullable();
20 |
21 | $table->text('two_factor_recovery_codes')
22 | ->after('two_factor_secret')
23 | ->nullable();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::table('users', function (Blueprint $table) {
35 | $table->dropColumn('two_factor_secret', 'two_factor_recovery_codes');
36 | });
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/web/database/migrations/2019_05_03_000001_create_customer_columns.php:
--------------------------------------------------------------------------------
1 | string('stripe_id')->nullable()->index();
18 | $table->string('card_brand')->nullable();
19 | $table->string('card_last_four', 4)->nullable();
20 | $table->timestamp('trial_ends_at')->nullable();
21 | });
22 | }
23 |
24 | /**
25 | * Reverse the migrations.
26 | *
27 | * @return void
28 | */
29 | public function down()
30 | {
31 | Schema::table('users', function (Blueprint $table) {
32 | $table->dropColumn([
33 | 'stripe_id',
34 | 'card_brand',
35 | 'card_last_four',
36 | 'trial_ends_at',
37 | ]);
38 | });
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/web/database/migrations/2019_05_03_000002_create_subscriptions_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('user_id');
19 | $table->string('name');
20 | $table->string('stripe_id');
21 | $table->string('stripe_status');
22 | $table->string('stripe_plan')->nullable();
23 | $table->integer('quantity')->nullable();
24 | $table->timestamp('trial_ends_at')->nullable();
25 | $table->timestamp('ends_at')->nullable();
26 | $table->timestamps();
27 |
28 | $table->index(['user_id', 'stripe_status']);
29 | });
30 | }
31 |
32 | /**
33 | * Reverse the migrations.
34 | *
35 | * @return void
36 | */
37 | public function down()
38 | {
39 | Schema::dropIfExists('subscriptions');
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/web/database/migrations/2019_05_03_000003_create_subscription_items_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->unsignedBigInteger('subscription_id');
19 | $table->string('stripe_id')->index();
20 | $table->string('stripe_plan');
21 | $table->integer('quantity')->nullable();
22 | $table->timestamps();
23 |
24 | $table->unique(['subscription_id', 'stripe_plan']);
25 | });
26 | }
27 |
28 | /**
29 | * Reverse the migrations.
30 | *
31 | * @return void
32 | */
33 | public function down()
34 | {
35 | Schema::dropIfExists('subscription_items');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/web/database/migrations/2019_08_19_000000_create_failed_jobs_table.php:
--------------------------------------------------------------------------------
1 | id();
18 | $table->string('uuid')->unique();
19 | $table->text('connection');
20 | $table->text('queue');
21 | $table->longText('payload');
22 | $table->longText('exception');
23 | $table->timestamp('failed_at')->useCurrent();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('failed_jobs');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/web/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->morphs('tokenable');
19 | $table->string('name');
20 | $table->string('token', 64)->unique();
21 | $table->text('abilities')->nullable();
22 | $table->timestamp('last_used_at')->nullable();
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('personal_access_tokens');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/web/database/migrations/2021_02_19_084258_create_sessions_table.php:
--------------------------------------------------------------------------------
1 | string('id')->primary();
18 | $table->foreignId('user_id')->nullable()->index();
19 | $table->string('ip_address', 45)->nullable();
20 | $table->text('user_agent')->nullable();
21 | $table->text('payload');
22 | $table->integer('last_activity')->index();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('sessions');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/web/database/migrations/2021_02_19_090050_add_level_to_users_tables.php:
--------------------------------------------------------------------------------
1 | integer('level')->nullable()->default(1);
18 | });
19 | }
20 |
21 | /**
22 | * Reverse the migrations.
23 | *
24 | * @return void
25 | */
26 | public function down()
27 | {
28 | Schema::table('users', function (Blueprint $table) {
29 | $table->dropColumn([
30 | 'level',
31 | ]);
32 | });
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/web/database/migrations/2021_02_20_065353_create_content_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('name');
19 | $table->string('url');
20 | $table->tinyInteger('match')->default(1);
21 | $table->tinyInteger('enabled')->default(1);
22 | $table->string('redirect_url');
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::table('content', function (Blueprint $table) {
35 | Schema::dropIfExists('content');
36 | });
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/web/database/migrations/2021_02_20_091827_create_plans_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('name');
19 | $table->string('stripe_price_id');
20 | $table->integer('member_count')->default(0);
21 | $table->tinyInteger('enabled')->default(1);
22 | $table->timestamps();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::table('plans', function (Blueprint $table) {
34 | Schema::dropIfExists('plans');
35 | });
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/web/database/migrations/2021_02_20_092033_create_content_to_plans_table.php:
--------------------------------------------------------------------------------
1 | foreignId('content_id');
18 | $table->foreignId('plans_id');
19 | });
20 | }
21 |
22 | /**
23 | * Reverse the migrations.
24 | *
25 | * @return void
26 | */
27 | public function down()
28 | {
29 | Schema::table('content_plans', function (Blueprint $table) {
30 | Schema::dropIfExists('content_plans');
31 | });
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/web/database/migrations/2021_02_22_045143_add_subscription_info_to_users_table.php:
--------------------------------------------------------------------------------
1 | date('subscription_expire_date')->nullable()->default('2021-01-23');
18 | });
19 | }
20 |
21 | /**
22 | * Reverse the migrations.
23 | *
24 | * @return void
25 | */
26 | public function down()
27 | {
28 | Schema::table('users', function (Blueprint $table) {
29 | $table->dropColumn('subscription_expire_date');
30 | });
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/web/database/migrations/2021_02_22_045431_create_payinfo_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->bigInteger('uid');
19 | $table->string('stripe_event_id');
20 | $table->string('stripe_price_id');
21 | $table->string('stripe_charge_id')->nullable();
22 | $table->date('old_expire_date')->nullable();
23 | $table->string('duration');
24 | $table->text('record');
25 | $table->timestamps();
26 | });
27 | }
28 |
29 | /**
30 | * Reverse the migrations.
31 | *
32 | * @return void
33 | */
34 | public function down()
35 | {
36 | Schema::table('payinfo', function (Blueprint $table) {
37 | Schema::dropIfExists('payinfo');
38 | });
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/web/database/migrations/2021_02_23_101504_create_settings_table.php:
--------------------------------------------------------------------------------
1 | id();
18 | $table->string('app_name')->nullable();
19 | $table->string('app_url')->nullable();
20 | $table->string('app_logo_url')->nullable();
21 | $table->string('app_icon_url')->nullable();
22 | $table->string('app_title')->nullable();
23 | $table->string('app_detail')->nullable();
24 |
25 | $table->string('mail_host')->nullable();
26 | $table->string('mail_port')->nullable();
27 | $table->string('mail_username')->nullable();
28 | $table->string('mail_password')->nullable();
29 | $table->string('mail_from_address')->nullable();
30 |
31 | $table->string('stripe_key')->nullable();
32 | $table->string('stripe_secret')->nullable();
33 |
34 | $table->string('prism_jwt_key')->nullable();
35 | $table->string('prism_target_url')->nullable();
36 | $table->string('prism_source_url')->nullable();
37 |
38 |
39 | $table->timestamps();
40 | });
41 | }
42 |
43 | /**
44 | * Reverse the migrations.
45 | *
46 | * @return void
47 | */
48 | public function down()
49 | {
50 | Schema::dropIfExists('settings');
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/web/database/seeders/DatabaseSeeder.php:
--------------------------------------------------------------------------------
1 | create();
21 | if( !$user = DB::table('users')->where(['name'=>'admin'])->first() )
22 | DB::table('users')->insert([
23 | 'name' => 'admin',
24 | 'email' => 'admin@memberprism.com',
25 | 'password' => Hash::make('admin'),
26 | 'level' => 9,
27 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
28 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s'),
29 | ]);
30 |
31 | if( !$settings = DB::table('settings')->where(['id'=>1])->first() )
32 | DB::table('settings')->insert([
33 | 'id'=>1,
34 | 'prism_jwt_key' => Str::random(16),
35 | 'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
36 | 'updated_at' => Carbon::now()->format('Y-m-d H:i:s'),
37 | ]);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/web/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "npm run development",
5 | "development": "mix",
6 | "watch": "mix watch",
7 | "watch-poll": "mix watch -- --watch-options-poll=1000",
8 | "hot": "mix watch --hot",
9 | "prod": "npm run production",
10 | "production": "mix --production"
11 | },
12 | "devDependencies": {
13 | "@tailwindcss/forms": "^0.2.1",
14 | "@tailwindcss/typography": "^0.3.0",
15 | "alpinejs": "^2.7.3",
16 | "autoprefixer": "^10.0.2",
17 | "axios": "^0.21",
18 | "laravel-mix": "^6.0.6",
19 | "lodash": "^4.17.19",
20 | "postcss": "^8.1.14",
21 | "postcss-import": "^12.0.1",
22 | "resolve-url-loader": "^3.1.2",
23 | "sass": "^1.32.8",
24 | "sass-loader": "^8.0.2",
25 | "tailwindcss": "^2.0.1"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/web/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | ./tests/Unit
10 |
11 |
12 | ./tests/Feature
13 |
14 |
15 |
16 |
17 | ./app
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/web/public/.htaccess:
--------------------------------------------------------------------------------
1 |
2 |
3 | Options -MultiViews -Indexes
4 |
5 |
6 | RewriteEngine On
7 |
8 | # Handle Authorization Header
9 | RewriteCond %{HTTP:Authorization} .
10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
11 |
12 | # Redirect Trailing Slashes If Not A Folder...
13 | RewriteCond %{REQUEST_FILENAME} !-d
14 | RewriteCond %{REQUEST_URI} (.+)/$
15 | RewriteRule ^ %1 [L,R=301]
16 |
17 | # Send Requests To Front Controller...
18 | RewriteCond %{REQUEST_FILENAME} !-d
19 | RewriteCond %{REQUEST_FILENAME} !-f
20 | RewriteRule ^ index.php [L]
21 |
22 |
--------------------------------------------------------------------------------
/web/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/easychen/MemberPrism2/6ca545d918dea8c4b6170d0ff2303883aac0ad9f/web/public/favicon.ico
--------------------------------------------------------------------------------
/web/public/index.php:
--------------------------------------------------------------------------------
1 | make(Kernel::class);
52 |
53 | $response = tap($kernel->handle(
54 | $request = Request::capture()
55 | ))->send();
56 |
57 | $kernel->terminate($request, $response);
58 |
--------------------------------------------------------------------------------
/web/public/mix-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "/js/app.js": "/js/app.js",
3 | "/site/app.js": "/site/app.js",
4 | "/css/app.css": "/css/app.css",
5 | "/site/app.css": "/site/app.css"
6 | }
7 |
--------------------------------------------------------------------------------
/web/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/web/public/site/app.css:
--------------------------------------------------------------------------------
1 | .book {
2 | font-size: 12px;
3 | }
4 |
--------------------------------------------------------------------------------
/web/public/site/app.js:
--------------------------------------------------------------------------------
1 | /******/ (() => { // webpackBootstrap
2 | var __webpack_exports__ = {};
3 | /*!***********************************!*\
4 | !*** ./resources/site/src/app.js ***!
5 | \***********************************/
6 | //
7 | /******/ })()
8 | ;
--------------------------------------------------------------------------------
/web/public/web.config:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/web/resources/css/app.css:
--------------------------------------------------------------------------------
1 | @import 'tailwindcss/base';
2 | @import 'tailwindcss/components';
3 | @import 'tailwindcss/utilities';
4 |
--------------------------------------------------------------------------------
/web/resources/js/app.js:
--------------------------------------------------------------------------------
1 | require('./bootstrap');
2 |
3 | require('alpinejs');
4 |
--------------------------------------------------------------------------------
/web/resources/js/bootstrap.js:
--------------------------------------------------------------------------------
1 | window._ = require('lodash');
2 |
3 | /**
4 | * We'll load the axios HTTP library which allows us to easily issue requests
5 | * to our Laravel back-end. This library automatically handles sending the
6 | * CSRF token as a header based on the value of the "XSRF" token cookie.
7 | */
8 |
9 | window.axios = require('axios');
10 |
11 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
12 |
13 | /**
14 | * Echo exposes an expressive API for subscribing to channels and listening
15 | * for events that are broadcast by Laravel. Echo and event broadcasting
16 | * allows your team to easily build robust real-time web applications.
17 | */
18 |
19 | // import Echo from 'laravel-echo';
20 |
21 | // window.Pusher = require('pusher-js');
22 |
23 | // window.Echo = new Echo({
24 | // broadcaster: 'pusher',
25 | // key: process.env.MIX_PUSHER_APP_KEY,
26 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER,
27 | // forceTLS: true
28 | // });
29 |
--------------------------------------------------------------------------------
/web/resources/lang/en/auth.php:
--------------------------------------------------------------------------------
1 | 'These credentials do not match our records.',
17 | 'password' => 'The provided password is incorrect.',
18 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
19 |
20 | ];
21 |
--------------------------------------------------------------------------------
/web/resources/lang/en/pagination.php:
--------------------------------------------------------------------------------
1 | '« Previous',
17 | 'next' => 'Next »',
18 |
19 | ];
20 |
--------------------------------------------------------------------------------
/web/resources/lang/en/passwords.php:
--------------------------------------------------------------------------------
1 | 'Your password has been reset!',
17 | 'sent' => 'We have emailed your password reset link!',
18 | 'throttled' => 'Please wait before retrying.',
19 | 'token' => 'This password reset token is invalid.',
20 | 'user' => "We can't find a user with that email address.",
21 |
22 | ];
23 |
--------------------------------------------------------------------------------
/web/resources/markdown/policy.md:
--------------------------------------------------------------------------------
1 | # Privacy Policy
2 |
3 | Edit this file to define the privacy policy for your application.
4 |
--------------------------------------------------------------------------------
/web/resources/markdown/terms.md:
--------------------------------------------------------------------------------
1 | # Terms of Service
2 |
3 | Edit this file to define the terms of service for your application.
4 |
--------------------------------------------------------------------------------
/web/resources/site/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/web/resources/site/headcode.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/web/resources/site/mix-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "/dist/app.js": "/dist/app.js",
3 | "/dist/app.css": "/dist/app.css"
4 | }
5 |
--------------------------------------------------------------------------------
/web/resources/site/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "site",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "webpack.mix.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "laravel-mix": "^6.0.11",
14 | "postcss": "^8.2.6"
15 | },
16 | "dependencies": {
17 | "axios": "^0.21.1",
18 | "js-cookie": "^2.2.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/web/resources/site/webpack.mix.js:
--------------------------------------------------------------------------------
1 | let mix = require('laravel-mix');
2 |
3 | mix.js(['src/alpine.min.js','src/app.js'], 'dist/app.js');
4 | mix.sass('src/app.scss', 'dist/app.css');
5 |
--------------------------------------------------------------------------------
/web/resources/views/admin/content/create.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Create Content') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.content-create')
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/admin/content/list.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Content') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.content')
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/admin/content/modify.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Modify Content') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.content-modify', ['content'=>$content->toArray()])
11 |
12 | @livewire('prism.admin.content-delete',['content'=>$content->toArray()])
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/web/resources/views/admin/links.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Links and code') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.links')
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/admin/members/list.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Members') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.members')
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/admin/members/modify.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Modify Member Info') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.members-modify', ['user'=>$user->toArray()])
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/admin/plans/create.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Create a plan') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.plan-create')
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/admin/plans/list.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Plans') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.plan')
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/admin/plans/modify.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Modify Plan') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.plan-modify', ['plan'=>$plan->toArray()])
11 |
12 | @livewire('prism.admin.plan-delete',['plan'=>$plan->toArray()])
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/web/resources/views/admin/settings.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Settings') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('prism.admin.settings')
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/api/index.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('API Tokens') }}
5 |
6 |
7 |
8 |
9 |
10 | @livewire('api.api-token-manager')
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/auth/confirm-password.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
9 |
10 |
11 |
12 |
13 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/web/resources/views/auth/forgot-password.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
9 |
10 |
11 | @if (session('status'))
12 |
13 | {{ session('status') }}
14 |
15 | @endif
16 |
17 |
18 |
19 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/web/resources/views/auth/login.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | @if (session('status'))
10 |
11 | {{ session('status') }}
12 |
13 | @endif
14 |
15 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/web/resources/views/auth/reset-password.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/web/resources/views/auth/verify-email.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
9 |
10 |
11 | @if (session('status') == 'verification-link-sent')
12 |
13 | {{ __('A new verification link has been sent to the email address you provided during registration.') }}
14 |
15 | @endif
16 |
17 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/web/resources/views/components/span.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
4 | {{ $slot }}
5 |
6 |
--------------------------------------------------------------------------------
/web/resources/views/dashboard.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Dashboard') }}
5 |
6 |
7 |
8 |
15 |
16 |
--------------------------------------------------------------------------------
/web/resources/views/layouts/app.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ config('app.name', 'Laravel') }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | @livewireStyles
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | @livewire('navigation-menu')
26 |
27 |
28 | @if (isset($header))
29 |
30 |
31 | {{ $header }}
32 |
33 |
34 | @endif
35 |
36 |
37 |
38 | {{ $slot }}
39 |
40 |
41 |
42 | @stack('modals')
43 |
44 | @livewireScripts
45 |
46 |
47 |
--------------------------------------------------------------------------------
/web/resources/views/layouts/guest.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ config('app.name', 'Laravel') }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{ $slot }}
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/web/resources/views/livewire/prism/admin/content-create.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Create a member-only content') }}
4 |
5 |
6 |
7 | {{ __('Only members can visit it .') }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | How to match the url
27 | @foreach($match_types as $key => $name)
28 | {{ $name }}
29 | @endforeach
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | {{ __('Saved.') }}
45 |
46 |
47 |
48 | {{ __('Save') }}
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/web/resources/views/livewire/prism/admin/content-delete.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Delete the content') }}
4 |
5 |
6 |
7 | {{ __('Cannot be revocerd .') }}
8 |
9 |
10 |
11 | Delete?
12 |
13 |
14 |
15 |
16 | {{ __('Deleted.') }}
17 |
18 |
19 | @if( $confirm )
20 | {{ __('Cancel') }}
21 |
22 | {{ __('Confirm') }}
23 |
24 | @else
25 | {{ __('Delete') }}
26 | @endif
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/web/resources/views/livewire/prism/admin/content-item.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{$content['name']}}
5 |
6 |
7 |
8 |
9 |
10 | {{$content['url']}}
11 |
12 |
13 |
14 |
15 |
16 | @if( $content['match'] == 1 )
17 | StartWith
18 | @else
19 | Exact
20 | @endif
21 |
22 |
23 |
24 |
25 |
26 | {{$content['redirect_url']}}
27 |
28 |
29 |
30 |
31 |
32 | @if( $content['enabled'] > 0 )
33 | Enabled
34 | @else
35 | Disabled
36 | @endif
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/web/resources/views/livewire/prism/admin/content-modify.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Modify the member-only content') }}
4 |
5 |
6 |
7 | {{ __('Only members can visit it .') }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | How to match the url
27 | @foreach($match_types as $key => $name)
28 | {{ $name }}
29 | @endforeach
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | {{ __('Saved.') }}
45 |
46 |
47 |
48 | {{ __('Save') }}
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/web/resources/views/livewire/prism/admin/member-item.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 | {{ $member['name'] }}
13 |
14 |
15 |
16 |
17 |
18 | {{ $member['email'] }}
20 |
21 |
22 | @if( $member['level'] > 1 )
23 | Admin
24 | @else
25 | User
26 | @endif
27 |
28 |
29 |
30 |
31 | =date("m/d/Y", strtotime($member['subscription_expire_date'])) ?>
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/web/resources/views/livewire/prism/admin/members-modify.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Modify the user') }}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | {{ __('Saved.') }}
40 |
41 |
42 |
43 | {{ __('Save') }}
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/web/resources/views/livewire/prism/admin/plan-create.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Create a plan') }}
4 |
5 |
6 |
7 | {{ __('Then members can subscribe it .') }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | {{ __('Saved.') }}
28 |
29 |
30 |
31 | {{ __('Save') }}
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/web/resources/views/livewire/prism/admin/plan-delete.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Delete the plan') }}
4 |
5 |
6 |
7 | {{ __('Cannot be revocerd .') }}
8 |
9 |
10 |
11 | Delete?
12 |
13 |
14 |
15 |
16 |
17 | {{ __('Deleted.') }}
18 |
19 |
20 | @if( $confirm )
21 | {{ __('Cancel') }}
22 |
23 | {{ __('Confirm') }}
24 |
25 | @else
26 | {{ __('Delete') }}
27 | @endif
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/web/resources/views/livewire/prism/admin/plan-modify.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Modify the plan') }}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | {{ __('Saved.') }}
28 |
29 |
30 |
31 | {{ __('Save') }}
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/web/resources/views/policy.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {!! $policy !!}
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/profile/show.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Profile') }}
5 |
6 |
7 |
8 |
9 |
10 | @if (Laravel\Fortify\Features::canUpdateProfileInformation())
11 | @livewire('profile.update-profile-information-form')
12 |
13 |
14 | @endif
15 |
16 | @if (Laravel\Fortify\Features::enabled(Laravel\Fortify\Features::updatePasswords()))
17 |
18 | @livewire('profile.update-password-form')
19 |
20 |
21 |
22 | @endif
23 |
24 | @if (Laravel\Fortify\Features::canManageTwoFactorAuthentication())
25 |
26 | @livewire('profile.two-factor-authentication-form')
27 |
28 |
29 |
30 | @endif
31 |
32 |
33 | @livewire('profile.logout-other-browser-sessions-form')
34 |
35 |
36 | @if (Laravel\Jetstream\Jetstream::hasAccountDeletionFeatures())
37 |
38 |
39 |
40 | @livewire('profile.delete-user-form')
41 |
42 | @endif
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/web/resources/views/profile/update-password-form.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ __('Update Password') }}
4 |
5 |
6 |
7 | {{ __('Ensure your account is using a long, random password to stay secure.') }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | {{ __('Saved.') }}
33 |
34 |
35 |
36 | {{ __('Save') }}
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/web/resources/views/terms.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {!! $terms !!}
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/action-message.blade.php:
--------------------------------------------------------------------------------
1 | @props(['on'])
2 |
3 | merge(['class' => 'text-sm text-gray-600']) }}>
8 | {{ $slot->isEmpty() ? 'Saved.' : $slot }}
9 |
10 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/action-section.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ $title }}
4 | {{ $description }}
5 |
6 |
7 |
8 |
9 | {{ $content }}
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/application-mark.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/authentication-card-logo.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/authentication-card.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ $logo }}
4 |
5 |
6 |
7 | {{ $slot }}
8 |
9 |
10 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/button.blade.php:
--------------------------------------------------------------------------------
1 | merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:shadow-outline-gray disabled:opacity-25 transition ease-in-out duration-150']) }}>
2 | {{ $slot }}
3 |
4 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/checkbox.blade.php:
--------------------------------------------------------------------------------
1 | merge(['class' => 'rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50']) !!}>
2 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/confirmation-modal.blade.php:
--------------------------------------------------------------------------------
1 | @props(['id' => null, 'maxWidth' => null])
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
14 | {{ $title }}
15 |
16 |
17 |
18 | {{ $content }}
19 |
20 |
21 |
22 |
23 |
24 |
25 | {{ $footer }}
26 |
27 |
28 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/confirms-password.blade.php:
--------------------------------------------------------------------------------
1 | @props(['title' => __('Confirm Password'), 'content' => __('For your security, please confirm your password to continue.'), 'button' => __('Confirm')])
2 |
3 | @php
4 | $confirmableId = md5($attributes->wire('then'));
5 | @endphp
6 |
7 | wire('then') }}
9 | x-data
10 | x-ref="span"
11 | x-on:click="$wire.startConfirmingPassword('{{ $confirmableId }}')"
12 | x-on:password-confirmed.window="setTimeout(() => $event.detail.id === '{{ $confirmableId }}' && $refs.span.dispatchEvent(new CustomEvent('then', { bubbles: false })), 250);"
13 | >
14 | {{ $slot }}
15 |
16 |
17 | @once
18 |
19 |
20 | {{ $title }}
21 |
22 |
23 |
24 | {{ $content }}
25 |
26 |
27 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | {{ __('Nevermind') }}
39 |
40 |
41 |
42 | {{ $button }}
43 |
44 |
45 |
46 | @endonce
47 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/danger-button.blade.php:
--------------------------------------------------------------------------------
1 | merge(['type' => 'button', 'class' => 'inline-flex items-center justify-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 focus:outline-none focus:border-red-700 focus:shadow-outline-red active:bg-red-600 transition ease-in-out duration-150']) }}>
2 | {{ $slot }}
3 |
4 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/dialog-modal.blade.php:
--------------------------------------------------------------------------------
1 | @props(['id' => null, 'maxWidth' => null])
2 |
3 |
4 |
5 |
6 | {{ $title }}
7 |
8 |
9 |
10 | {{ $content }}
11 |
12 |
13 |
14 |
15 | {{ $footer }}
16 |
17 |
18 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/dropdown-link.blade.php:
--------------------------------------------------------------------------------
1 | merge(['class' => 'block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 transition duration-150 ease-in-out']) }}>{{ $slot }}
2 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/dropdown.blade.php:
--------------------------------------------------------------------------------
1 | @props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white', 'dropdownClasses' => ''])
2 |
3 | @php
4 | switch ($align) {
5 | case 'left':
6 | $alignmentClasses = 'origin-top-left left-0';
7 | break;
8 | case 'top':
9 | $alignmentClasses = 'origin-top';
10 | break;
11 | case 'none':
12 | case 'false':
13 | $alignmentClasses = '';
14 | break;
15 | case 'right':
16 | default:
17 | $alignmentClasses = 'origin-top-right right-0';
18 | break;
19 | }
20 |
21 | switch ($width) {
22 | case '48':
23 | $width = 'w-48';
24 | break;
25 | }
26 | @endphp
27 |
28 |
29 |
30 | {{ $trigger }}
31 |
32 |
33 |
43 |
44 | {{ $content }}
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/form-section.blade.php:
--------------------------------------------------------------------------------
1 | @props(['submit'])
2 |
3 | merge(['class' => 'md:grid md:grid-cols-3 md:gap-6']) }}>
4 |
5 | {{ $title }}
6 | {{ $description }}
7 |
8 |
9 |
24 |
25 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/input-error.blade.php:
--------------------------------------------------------------------------------
1 | @props(['for'])
2 |
3 | @error($for)
4 | merge(['class' => 'text-sm text-red-600']) }}>{{ $message }}
5 | @enderror
6 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/input.blade.php:
--------------------------------------------------------------------------------
1 | @props(['disabled' => false])
2 |
3 | merge(['class' => 'border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm']) !!}>
4 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/label.blade.php:
--------------------------------------------------------------------------------
1 | @props(['value'])
2 |
3 | merge(['class' => 'block font-medium text-sm text-gray-700']) }}>
4 | {{ $value ?? $slot }}
5 |
6 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/nav-link.blade.php:
--------------------------------------------------------------------------------
1 | @props(['active'])
2 |
3 | @php
4 | $classes = ($active ?? false)
5 | ? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
6 | : 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out';
7 | @endphp
8 |
9 | merge(['class' => $classes]) }}>
10 | {{ $slot }}
11 |
12 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/responsive-nav-link.blade.php:
--------------------------------------------------------------------------------
1 | @props(['active'])
2 |
3 | @php
4 | $classes = ($active ?? false)
5 | ? 'block pl-3 pr-4 py-2 border-l-4 border-indigo-400 text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out'
6 | : 'block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out';
7 | @endphp
8 |
9 | merge(['class' => $classes]) }}>
10 | {{ $slot }}
11 |
12 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/secondary-button.blade.php:
--------------------------------------------------------------------------------
1 | merge(['type' => 'button', 'class' => 'inline-flex items-center px-4 py-2 bg-white border border-gray-300 rounded-md font-semibold text-xs text-gray-700 uppercase tracking-widest shadow-sm hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:text-gray-800 active:bg-gray-50 transition ease-in-out duration-150']) }}>
2 | {{ $slot }}
3 |
4 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/section-border.blade.php:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/section-title.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ $title }}
4 |
5 |
6 | {{ $description }}
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/switchable-team.blade.php:
--------------------------------------------------------------------------------
1 | @props(['team', 'component' => 'jet-dropdown-link'])
2 |
3 |
20 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/validation-errors.blade.php:
--------------------------------------------------------------------------------
1 | @if ($errors->any())
2 |
3 |
{{ __('Whoops! Something went wrong.') }}
4 |
5 |
6 | @foreach ($errors->all() as $error)
7 | {{ $error }}
8 | @endforeach
9 |
10 |
11 | @endif
12 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/components/welcome.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ env('APP_TITLE') }}
8 |
9 |
10 |
11 | {{ env('APP_DETAIL') }}
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/web/resources/views/vendor/jetstream/mail/team-invitation.blade.php:
--------------------------------------------------------------------------------
1 | @component('mail::message')
2 | {{ __('You have been invited to join the :team team!', ['team' => $invitation->team->name]) }}
3 |
4 | {{ __('If you do not have an account, you may create one by clicking the button below. After creating an account, you may click the invitation acceptance button in this email to accept the team invitation:') }}
5 |
6 | @component('mail::button', ['url' => route('register')])
7 | {{ __('Create Account') }}
8 | @endcomponent
9 |
10 | {{ __('If you already have an account, you may accept this invitation by clicking the button below:') }}
11 |
12 | @component('mail::button', ['url' => $acceptUrl])
13 | {{ __('Accept Invitation') }}
14 | @endcomponent
15 |
16 | {{ __('If you did not expect to receive an invitation to this team, you may discard this email.') }}
17 | @endcomponent
18 |
--------------------------------------------------------------------------------
/web/routes/api.php:
--------------------------------------------------------------------------------
1 | get('/user', function (Request $request) {
18 | return $request->user();
19 | });
20 |
21 |
22 | Route::post('/register' , 'Laravel\Fortify\Http\Controllers\RegisteredUserController@store' );
23 |
24 | Route::post('/login' , 'App\Http\Controllers\ApiController@login' );
25 | Route::get('/lock' , 'App\Http\Controllers\ApiController@lock' );
26 |
27 | Route::middleware('jwt')->post('/subscribe' , 'App\Http\Controllers\ApiController@subscribe' );
28 |
29 | Route::middleware('jwt')->post('/stripe_port' , 'App\Http\Controllers\ApiController@stripeport' );
30 |
31 | Route::get('/stripe/callback' , 'App\Http\Controllers\ApiController@payback' )->name('stripe.payback');
32 |
33 | Route::post('/forgot-password' , 'Laravel\Fortify\Http\Controllers\PasswordResetLinkController@store' );
34 |
35 | Route::get('/page/{page_name}', 'App\Http\Controllers\AssertController@page' );
36 | Route::get('/app.js', 'App\Http\Controllers\AssertController@js' );
37 | Route::get('/app.css', 'App\Http\Controllers\AssertController@css' );
38 |
--------------------------------------------------------------------------------
/web/routes/channels.php:
--------------------------------------------------------------------------------
1 | id === (int) $id;
18 | });
19 |
--------------------------------------------------------------------------------
/web/routes/console.php:
--------------------------------------------------------------------------------
1 | comment(Inspiring::quote());
19 | })->purpose('Display an inspiring quote');
20 |
--------------------------------------------------------------------------------
/web/server.php:
--------------------------------------------------------------------------------
1 |
8 | */
9 |
10 | $uri = urldecode(
11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
12 | );
13 |
14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the
15 | // built-in PHP web server. This provides a convenient way to test a Laravel
16 | // application without having installed a "real" web server software here.
17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) {
18 | return false;
19 | }
20 |
21 | require_once __DIR__.'/public/index.php';
22 |
--------------------------------------------------------------------------------
/web/storage/app/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !public/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/web/storage/app/public/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/web/storage/framework/.gitignore:
--------------------------------------------------------------------------------
1 | compiled.php
2 | config.php
3 | down
4 | events.scanned.php
5 | maintenance.php
6 | routes.php
7 | routes.scanned.php
8 | schedule-*
9 | services.json
10 |
--------------------------------------------------------------------------------
/web/storage/framework/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !data/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/web/storage/framework/cache/data/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/web/storage/framework/sessions/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/web/storage/framework/testing/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/web/storage/framework/views/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/web/storage/logs/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/web/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const defaultTheme = require('tailwindcss/defaultTheme');
2 |
3 | module.exports = {
4 | purge: [
5 | './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
6 | './vendor/laravel/jetstream/**/*.blade.php',
7 | './storage/framework/views/*.php',
8 | './resources/views/**/*.blade.php',
9 | ],
10 |
11 | theme: {
12 | extend: {
13 | fontFamily: {
14 | sans: ['Nunito', ...defaultTheme.fontFamily.sans],
15 | },
16 | },
17 | },
18 |
19 | variants: {
20 | extend: {
21 | opacity: ['disabled'],
22 | },
23 | },
24 |
25 | plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography')],
26 | };
27 |
--------------------------------------------------------------------------------
/web/tests/CreatesApplication.php:
--------------------------------------------------------------------------------
1 | make(Kernel::class)->bootstrap();
19 |
20 | return $app;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/web/tests/Feature/ApiTokenPermissionsTest.php:
--------------------------------------------------------------------------------
1 | markTestSkipped('API support is not enabled.');
21 | }
22 |
23 | $this->actingAs($user = User::factory()->withPersonalTeam()->create());
24 |
25 | $token = $user->tokens()->create([
26 | 'name' => 'Test Token',
27 | 'token' => Str::random(40),
28 | 'abilities' => ['create', 'read'],
29 | ]);
30 |
31 | Livewire::test(ApiTokenManager::class)
32 | ->set(['managingPermissionsFor' => $token])
33 | ->set(['updateApiTokenForm' => [
34 | 'permissions' => [
35 | 'delete',
36 | 'missing-permission',
37 | ],
38 | ]])
39 | ->call('updateApiToken');
40 |
41 | $this->assertTrue($user->fresh()->tokens->first()->can('delete'));
42 | $this->assertFalse($user->fresh()->tokens->first()->can('read'));
43 | $this->assertFalse($user->fresh()->tokens->first()->can('missing-permission'));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/web/tests/Feature/AuthenticationTest.php:
--------------------------------------------------------------------------------
1 | get('/login');
17 |
18 | $response->assertStatus(200);
19 | }
20 |
21 | public function test_users_can_authenticate_using_the_login_screen()
22 | {
23 | $user = User::factory()->create();
24 |
25 | $response = $this->post('/login', [
26 | 'email' => $user->email,
27 | 'password' => 'password',
28 | ]);
29 |
30 | $this->assertAuthenticated();
31 | $response->assertRedirect(RouteServiceProvider::HOME);
32 | }
33 |
34 | public function test_users_can_not_authenticate_with_invalid_password()
35 | {
36 | $user = User::factory()->create();
37 |
38 | $this->post('/login', [
39 | 'email' => $user->email,
40 | 'password' => 'wrong-password',
41 | ]);
42 |
43 | $this->assertGuest();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/web/tests/Feature/BrowserSessionsTest.php:
--------------------------------------------------------------------------------
1 | actingAs($user = User::factory()->create());
18 |
19 | Livewire::test(LogoutOtherBrowserSessionsForm::class)
20 | ->set('password', 'password')
21 | ->call('logoutOtherBrowserSessions');
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/web/tests/Feature/CreateApiTokenTest.php:
--------------------------------------------------------------------------------
1 | markTestSkipped('API support is not enabled.');
20 | }
21 |
22 | $this->actingAs($user = User::factory()->withPersonalTeam()->create());
23 |
24 | Livewire::test(ApiTokenManager::class)
25 | ->set(['createApiTokenForm' => [
26 | 'name' => 'Test Token',
27 | 'permissions' => [
28 | 'read',
29 | 'update',
30 | ],
31 | ]])
32 | ->call('createApiToken');
33 |
34 | $this->assertCount(1, $user->fresh()->tokens);
35 | $this->assertEquals('Test Token', $user->fresh()->tokens->first()->name);
36 | $this->assertTrue($user->fresh()->tokens->first()->can('read'));
37 | $this->assertFalse($user->fresh()->tokens->first()->can('delete'));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/web/tests/Feature/DeleteAccountTest.php:
--------------------------------------------------------------------------------
1 | markTestSkipped('Account deletion is not enabled.');
20 | }
21 |
22 | $this->actingAs($user = User::factory()->create());
23 |
24 | $component = Livewire::test(DeleteUserForm::class)
25 | ->set('password', 'password')
26 | ->call('deleteUser');
27 |
28 | $this->assertNull($user->fresh());
29 | }
30 |
31 | public function test_correct_password_must_be_provided_before_account_can_be_deleted()
32 | {
33 | if (! Features::hasAccountDeletionFeatures()) {
34 | return $this->markTestSkipped('Account deletion is not enabled.');
35 | }
36 |
37 | $this->actingAs($user = User::factory()->create());
38 |
39 | Livewire::test(DeleteUserForm::class)
40 | ->set('password', 'wrong-password')
41 | ->call('deleteUser')
42 | ->assertHasErrors(['password']);
43 |
44 | $this->assertNotNull($user->fresh());
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/web/tests/Feature/DeleteApiTokenTest.php:
--------------------------------------------------------------------------------
1 | markTestSkipped('API support is not enabled.');
21 | }
22 |
23 | $this->actingAs($user = User::factory()->withPersonalTeam()->create());
24 |
25 | $token = $user->tokens()->create([
26 | 'name' => 'Test Token',
27 | 'token' => Str::random(40),
28 | 'abilities' => ['create', 'read'],
29 | ]);
30 |
31 | Livewire::test(ApiTokenManager::class)
32 | ->set(['apiTokenIdBeingDeleted' => $token->id])
33 | ->call('deleteApiToken');
34 |
35 | $this->assertCount(0, $user->fresh()->tokens);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/web/tests/Feature/ExampleTest.php:
--------------------------------------------------------------------------------
1 | get('/');
18 |
19 | $response->assertStatus(200);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/web/tests/Feature/PasswordConfirmationTest.php:
--------------------------------------------------------------------------------
1 | withPersonalTeam()->create()
18 | : User::factory()->create();
19 |
20 | $response = $this->actingAs($user)->get('/user/confirm-password');
21 |
22 | $response->assertStatus(200);
23 | }
24 |
25 | public function test_password_can_be_confirmed()
26 | {
27 | $user = User::factory()->create();
28 |
29 | $response = $this->actingAs($user)->post('/user/confirm-password', [
30 | 'password' => 'password',
31 | ]);
32 |
33 | $response->assertRedirect();
34 | $response->assertSessionHasNoErrors();
35 | }
36 |
37 | public function test_password_is_not_confirmed_with_invalid_password()
38 | {
39 | $user = User::factory()->create();
40 |
41 | $response = $this->actingAs($user)->post('/user/confirm-password', [
42 | 'password' => 'wrong-password',
43 | ]);
44 |
45 | $response->assertSessionHasErrors();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/web/tests/Feature/ProfileInformationTest.php:
--------------------------------------------------------------------------------
1 | actingAs($user = User::factory()->create());
18 |
19 | $component = Livewire::test(UpdateProfileInformationForm::class);
20 |
21 | $this->assertEquals($user->name, $component->state['name']);
22 | $this->assertEquals($user->email, $component->state['email']);
23 | }
24 |
25 | public function test_profile_information_can_be_updated()
26 | {
27 | $this->actingAs($user = User::factory()->create());
28 |
29 | Livewire::test(UpdateProfileInformationForm::class)
30 | ->set('state', ['name' => 'Test Name', 'email' => 'test@example.com'])
31 | ->call('updateProfileInformation');
32 |
33 | $this->assertEquals('Test Name', $user->fresh()->name);
34 | $this->assertEquals('test@example.com', $user->fresh()->email);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/web/tests/Feature/RegistrationTest.php:
--------------------------------------------------------------------------------
1 | get('/register');
17 |
18 | $response->assertStatus(200);
19 | }
20 |
21 | public function test_new_users_can_register()
22 | {
23 | $response = $this->post('/register', [
24 | 'name' => 'Test User',
25 | 'email' => 'test@example.com',
26 | 'password' => 'password',
27 | 'password_confirmation' => 'password',
28 | 'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(),
29 | ]);
30 |
31 | $this->assertAuthenticated();
32 | $response->assertRedirect(RouteServiceProvider::HOME);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/web/tests/Feature/TwoFactorAuthenticationSettingsTest.php:
--------------------------------------------------------------------------------
1 | actingAs($user = User::factory()->create());
18 |
19 | $this->withSession(['auth.password_confirmed_at' => time()]);
20 |
21 | Livewire::test(TwoFactorAuthenticationForm::class)
22 | ->call('enableTwoFactorAuthentication');
23 |
24 | $user = $user->fresh();
25 |
26 | $this->assertNotNull($user->two_factor_secret);
27 | $this->assertCount(8, $user->recoveryCodes());
28 | }
29 |
30 | public function test_recovery_codes_can_be_regenerated()
31 | {
32 | $this->actingAs($user = User::factory()->create());
33 |
34 | $this->withSession(['auth.password_confirmed_at' => time()]);
35 |
36 | $component = Livewire::test(TwoFactorAuthenticationForm::class)
37 | ->call('enableTwoFactorAuthentication')
38 | ->call('regenerateRecoveryCodes');
39 |
40 | $user = $user->fresh();
41 |
42 | $component->call('regenerateRecoveryCodes');
43 |
44 | $this->assertCount(8, $user->recoveryCodes());
45 | $this->assertCount(8, array_diff($user->recoveryCodes(), $user->fresh()->recoveryCodes()));
46 | }
47 |
48 | public function test_two_factor_authentication_can_be_disabled()
49 | {
50 | $this->actingAs($user = User::factory()->create());
51 |
52 | $this->withSession(['auth.password_confirmed_at' => time()]);
53 |
54 | $component = Livewire::test(TwoFactorAuthenticationForm::class)
55 | ->call('enableTwoFactorAuthentication');
56 |
57 | $this->assertNotNull($user->fresh()->two_factor_secret);
58 |
59 | $component->call('disableTwoFactorAuthentication');
60 |
61 | $this->assertNull($user->fresh()->two_factor_secret);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/web/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | assertTrue(true);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/web/webpack.mix.js:
--------------------------------------------------------------------------------
1 | const mix = require('laravel-mix');
2 |
3 | /*
4 | |--------------------------------------------------------------------------
5 | | Mix Asset Management
6 | |--------------------------------------------------------------------------
7 | |
8 | | Mix provides a clean, fluent API for defining some Webpack build steps
9 | | for your Laravel applications. By default, we are compiling the CSS
10 | | file for the application as well as bundling up all the JS files.
11 | |
12 | */
13 |
14 | mix.js('resources/js/app.js', 'public/js')
15 | .postCss('resources/css/app.css', 'public/css', [
16 | require('postcss-import'),
17 | require('tailwindcss'),
18 | require('autoprefixer'),
19 | ]);
20 |
21 | if (mix.inProduction()) {
22 | mix.version();
23 | }
24 |
--------------------------------------------------------------------------------