Compare commits

..

17 Commits

Author SHA1 Message Date
surtur 3a155798a9
rm: get rid of unused launch settings
[skip ci]
2020-12-02 03:08:43 +01:00
surtur 3f775a110b
fix: clean build after restore
All checks were successful
continuous-integration/drone/push Build is passing
* this fixes occasional situation when NuGets have not been restored yet
  but the clean build already running required them, which resulted a
  failed build
2020-11-29 21:08:11 +01:00
surtur 42c6dfd3ba
chore: update make kaniko
All checks were successful
continuous-integration/drone/push Build is passing
* skip ci
2020-11-27 20:05:30 +01:00
surtur 1cc3df6619
chore: rm debug ls call
skip ci
2020-11-27 18:58:48 +01:00
surtur befe7880fc
revert: set kaniko context back to "."
skip ci
2020-11-27 18:58:27 +01:00
surtur 15d7de1996
chore: add make kaniko
* skip ci
2020-11-27 18:58:06 +01:00
surtur 5ed341f4ae
refactor: merge pipelines back
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 17:13:27 +01:00
surtur 732cd7d717
chore: don't wait and build
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 17:12:39 +01:00
surtur 11a9ab07ab
revert: kaniko don't give a **** about relpaths
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 17:11:08 +01:00
surtur a581457326
debug: see where we are
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 16:23:28 +01:00
surtur 1ef9a6831f
chore: try /src workspace for kaniko
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 15:58:50 +01:00
surtur 11d796f0dd
chore: add /src context for kaniko
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 15:30:21 +01:00
surtur 4b58c3f584
fix: rel paths are nicer to kaniko
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 15:22:18 +01:00
surtur 63601f7f47
chore: run wherever
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 15:16:57 +01:00
surtur 54fb45ec65
refactor: effectively revert 907a470 and 63bde0a
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 15:06:42 +01:00
surtur eece1e3dba
chore: move dockerbuilds to a separate pipeline
Some checks failed
continuous-integration/drone/push Build is failing
* and run them on the main runner
2020-11-27 14:52:23 +01:00
surtur 907a4702d8
chore: give kaniko relative paths in Dockerfile
Some checks reported errors
continuous-integration/drone/push Build was killed
2020-11-27 14:47:03 +01:00
128 changed files with 649 additions and 4493 deletions

View File

@ -1,13 +0,0 @@
docker-compose.yml
.dockerignore
.gitignore
bin/
obj/
.git
.vs
.vscode
.aspnet
.dotnet
.nuget
.local
.*.env

View File

@ -7,75 +7,33 @@ platform:
os: linux
arch: amd64
trigger:
ref:
- refs/heads/master
- refs/heads/feature-*
- refs/pull/*/head
- refs/tags/*
steps:
- name: restore
pull: always
image: mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
volumes:
- name: pkgcache
path: /root/.nuget/packages
depends_on: [clone]
commands:
- dotnet restore
- name: debug
pull: always
image: mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
volumes:
- name: pkgcache
path: /root/.nuget/packages
depends_on: [restore]
image: mcr.microsoft.com/dotnet/core/sdk:2.1-alpine
commands:
- dotnet restore
- dotnet build .
- name: release
pull: always
image: mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
volumes:
- name: pkgcache
path: /root/.nuget/packages
depends_on: [restore]
image: mcr.microsoft.com/dotnet/core/sdk:2.1-alpine
commands:
- dotnet publish -c Release -o out
- name: hadolint release
image: hadolint/hadolint:v1.23.0-8-gb01c5a9-alpine
depends_on: [clone]
commands:
- hadolint --version
- hadolint Dockerfile
- name: hadolint debug
image: hadolint/hadolint:v1.23.0-8-gb01c5a9-alpine
depends_on: [clone]
commands:
- hadolint --version
- hadolint Dockerfile.dev
- dotnet restore
- dotnet clean
- dotnet publish -c Release
- name: docker-release-build
pull: always
image: immawanderer/drone-kaniko:linux-amd64
depends_on: [release, hadolint release]
image: banzaicloud/drone-kaniko
settings:
dockerfile: Dockerfile
context: .
- name: docker-debug-build
pull: always
image: immawanderer/drone-kaniko:linux-amd64
depends_on: [debug, hadolint debug]
image: banzaicloud/drone-kaniko
settings:
dockerfile: Dockerfile.dev
context: .
volumes:
- name: pkgcache
temp: {}

View File

@ -1,30 +0,0 @@
[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = tab
indent_size = 4
tab_width = 4
[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}]
end_of_line = lf
indent_style = space
indent_size = 2
[{*.yaml,*.yml}]
end_of_line = lf
indent_style = space
indent_size = 2
[*.js.map]
end_of_line = lf
indent_style = space
indent_size = 2
[*.{appxmanifest,asax,ascx,aspx,axaml,build,cg,cginc,compute,cs,cshtml,dtd,hlsl,hlsli,hlslinc,master,nuspec,paml,razor,resw,resx,skin,usf,ush,vb,xaml,xamlx,xoml,xsd}]
end_of_line = lf
indent_style = tab
indent_size = 4
tab_width = 4

View File

@ -1,3 +0,0 @@
POSTGRES_USER=postgres
POSTGRES_PASSWORD=a6a204ca41effac89a0696ec8c652ba8b6b668129d55b5085eb4453ccb214343481bd0a61b889f1e2ec2ad58d267edf623898892b6cd042f93ad17610871da58
POSTGRES_INITDB_ARGS="--data-checksums"

View File

@ -1,3 +0,0 @@
DOTNET_CLI_TELEMETRY_OPTOUT=true
ASPNETCORE_ENVIRONMENT=Production
DB_CONNECTION_STRING="User ID=postgres;Password=a6a204ca41effac89a0696ec8c652ba8b6b668129d55b5085eb4453ccb214343481bd0a61b889f1e2ec2ad58d267edf623898892b6cd042f93ad17610871da58;Server=db;Port=5432;Database=pwt;Integrated Security=true;Pooling=true;"

14
.gitignore vendored
View File

@ -4,17 +4,3 @@ obj/
riderModule.iml
/_ReSharper.Caches/
*.swp
.dotnet/
.aspnet/
.nuget/
.local/
.idea/
.vscode/
.vs/
.ash_history
*.jpg
*.jpeg
*.png
.*.env

View File

@ -1,3 +0,0 @@
ignored:
# ad "SC2039 In POSIX sh, UID is undefined." - it's a var defined by us
- SC2039

View File

@ -1,125 +1,98 @@
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Authorization;
using pwt_0x01_ng.Models;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.Identity;
using pwt_0x01_ng.Models.Dbfake;
namespace pwt_0x01_ng.Areas.Admin.Controllers
{
[Area("Admin")]
[Authorize(Roles = nameof(Roles.Admin) + "," + nameof(Roles.Manager))]
public class CarouselController : Controller
{
IWebHostEnvironment hosting_env;
readonly DBContext dbctx;
[Area("Admin")]
public class CarouselController : Controller
{
IHostingEnvironment hosting_env;
private IList<Carousel> Carousels = Dbfake.Carousels;
public CarouselController(DBContext dbctx, IWebHostEnvironment hosting_env){
this.dbctx = dbctx;
this.hosting_env = hosting_env;
}
public CarouselController(IHostingEnvironment hosting_env){
this.hosting_env = hosting_env;
}
// GET
public async Task <IActionResult> Select()
{
CarouselViewModel carousel = new CarouselViewModel();
carousel.Carousels = await dbctx.Carousel.ToListAsync();
return View(carousel);
}
// GET
public IActionResult Select()
{
CarouselViewModel carousel = new CarouselViewModel();
carousel.Carousels = Carousels;
return View(carousel);
}
public IActionResult Create()
{
return View();
}
public IActionResult Create()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Create(Carousel carousel)
{
if (ModelState.IsValid) {
MegaUpload mega_upload = new MegaUpload(hosting_env.WebRootPath, "carousels", "image");
if ((carousel.ImageSrc = await mega_upload.DoMegaUpload(carousel.Image)) != string.Empty){/* all good here */}
[HttpPost]
public async Task<IActionResult> Create(Carousel carousel)
{
carousel.ImageSrc = string.Empty;
MegaUpload mega_upload = new MegaUpload(hosting_env);
await mega_upload.DoMegaUpload(carousel);
dbctx.Carousel.Add(carousel);
await dbctx.SaveChangesAsync();
return RedirectToAction(nameof(Select));
} else {
string errors = "";
for (int i = 0; i < ModelState.Values.Count(); i++){
for (int j = 0; j < ModelState.Values.ElementAt(i).Errors.Count(); j++){
errors += "\n " + ModelState.Values.ElementAt(i).Errors.ElementAt(j).ToString();
}
}
ViewData["Message"] = $"error creating Carousel => \n{errors}" + errors;
return View(carousel);
}
}
Carousels.Add(carousel);
return RedirectToAction(nameof(Select));
}
public IActionResult Edit(int id)
{
Carousel carousel_item = dbctx.Carousel.Where(c_item => c_item.id == id).FirstOrDefault();
if (carousel_item != null)
{
ViewData["ImageSrc"] = new SelectList(dbctx.Carousel, "ImageSrc", carousel_item.ImageSrc);
return View(carousel_item);
}
else
{
return NotFound();
}
}
public IActionResult Edit(int id)
{
Carousel carousel_item = Carousels.Where(c_item => c_item.id == id).FirstOrDefault();
if (carousel_item != null)
{
return View(carousel_item);
}
else
{
return NotFound();
}
}
[HttpPost]
public async Task<IActionResult> Edit(Carousel carousel)
{
Carousel carousel_item = dbctx.Carousel.Where(c_item => c_item.id == carousel.id).FirstOrDefault();
[HttpPost]
public async Task<IActionResult> Edit(Carousel carousel)
{
Carousel carousel_item = Carousels.Where(c_item => c_item.id == carousel.id).FirstOrDefault();
if (carousel_item != null)
{
if (ModelState.IsValid) {
carousel_item.id = carousel.id;
carousel_item.DataTarget = carousel.DataTarget;
carousel_item.ImageAlt = carousel.ImageAlt;
carousel_item.CarouselContent = carousel.CarouselContent;
if (carousel_item != null)
{
carousel_item.id = carousel.id;
carousel_item.DataTarget = carousel.DataTarget;
carousel_item.ImageAlt = carousel.ImageAlt;
carousel_item.CarouselContent = carousel.CarouselContent;
MegaUpload mega_upload = new MegaUpload(hosting_env.WebRootPath, "carousels", "image");
if ((carousel.ImageSrc = await mega_upload.DoMegaUpload(carousel.Image)) != string.Empty){
carousel_item.ImageSrc = carousel.ImageSrc;
}
await dbctx.SaveChangesAsync();
return RedirectToAction(nameof(Select));
}
string errors = "";
for (int i = 0; i < ModelState.Values.Count(); i++){
for (int j = 0; j < ModelState.Values.ElementAt(i).Errors.Count(); j++){
errors += "\n " + ModelState.Values.ElementAt(i).Errors.ElementAt(j).ToString();
}
}
ViewData["Message"] = "error editing Carousel => \n" + errors;
return View(carousel_item);
}
else
{
return NotFound();
}
}
MegaUpload mega_upload = new MegaUpload(hosting_env);
if (await mega_upload.DoMegaUpload(carousel)){
carousel_item.ImageSrc = carousel.ImageSrc;
}
return RedirectToAction(nameof(Select));
}
else
{
return NotFound();
}
}
public async Task <IActionResult> Delete(int id)
{
Carousel carousel_item = dbctx.Carousel.Where(c_item => c_item.id == id).FirstOrDefault();
if (carousel_item != null)
{
dbctx.Carousel.Remove(carousel_item);
await dbctx.SaveChangesAsync();
return RedirectToAction(nameof(Select));
}
else
{
return NotFound();
}
}
}
public IActionResult Delete(int id)
{
Carousel carousel_item = Carousels.Where(c_item => c_item.id == id).FirstOrDefault();
if (carousel_item != null)
{
Carousels.Remove(carousel_item);
return RedirectToAction(nameof(Select));
}
else
{
return NotFound();
}
}
}
}

View File

@ -1,168 +0,0 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;
using pwt_0x01_ng.Models;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.Identity;
namespace pwt_0x01_ng.Areas.Admin.Controllers
{
[Area("Admin")]
[Authorize(Roles = nameof(Roles.Admin))]
public class OrderItemController : Controller
{
private readonly DBContext _context;
public OrderItemController(DBContext context)
{
_context = context;
}
// GET: Admin/OrderItem
public async Task<IActionResult> Index()
{
var dBContext = _context.OrderItem.Include(o => o.Order).Include(o => o.Product);
return View(await dBContext.ToListAsync());
}
// GET: Admin/OrderItem/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var orderItem = await _context.OrderItem
.Include(o => o.Order)
.Include(o => o.Product)
.FirstOrDefaultAsync(m => m.id == id);
if (orderItem == null)
{
return NotFound();
}
return View(orderItem);
}
// GET: Admin/OrderItem/Create
public IActionResult Create()
{
ViewData["Order_id"] = new SelectList(_context.Order, "id", "Order_Number");
ViewData["Product_id"] = new SelectList(_context.Product, "id", "Description");
return View();
}
// POST: Admin/OrderItem/Create
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Order_id,Product_id,Amount,Price,id,Created,Updated")] OrderItem orderItem)
{
if (ModelState.IsValid)
{
_context.Add(orderItem);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["Order_id"] = new SelectList(_context.Order, "id", "Order_Number", orderItem.Order_id);
ViewData["Product_id"] = new SelectList(_context.Product, "id", "Description", orderItem.Product_id);
return View(orderItem);
}
// GET: Admin/OrderItem/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var orderItem = await _context.OrderItem.FindAsync(id);
if (orderItem == null)
{
return NotFound();
}
ViewData["Order_id"] = new SelectList(_context.Order, "id", "Order_Number", orderItem.Order_id);
ViewData["Product_id"] = new SelectList(_context.Product, "id", "Description", orderItem.Product_id);
return View(orderItem);
}
// POST: Admin/OrderItem/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Order_id,Product_id,Amount,Price,id,new.Created,new.Updated")] OrderItem orderItem)
{
if (id != orderItem.id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(orderItem);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!OrderItemExists(orderItem.id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["Order_id"] = new SelectList(_context.Order, "id", "Order_Number", orderItem.Order_id);
ViewData["Product_id"] = new SelectList(_context.Product, "id", "Description", orderItem.Product_id);
return View(orderItem);
}
// GET: Admin/OrderItem/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var orderItem = await _context.OrderItem
.Include(o => o.Order)
.Include(o => o.Product)
.FirstOrDefaultAsync(m => m.id == id);
if (orderItem == null)
{
return NotFound();
}
return View(orderItem);
}
// POST: Admin/OrderItem/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var orderItem = await _context.OrderItem.FindAsync(id);
_context.OrderItem.Remove(orderItem);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool OrderItemExists(int id)
{
return _context.OrderItem.Any(e => e.id == id);
}
}
}

View File

@ -1,158 +0,0 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Rendering;
using pwt_0x01_ng.Models;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.Identity;
namespace pwt_0x01_ng.Areas.Admin.Controllers
{
[Area("Admin")]
[Authorize(Roles = nameof(Roles.Admin) + "," + nameof(Roles.Manager))]
public class OrdersController : Controller
{
private readonly DBContext _context;
public OrdersController(DBContext context)
{
_context = context;
}
// GET: Admin/Orders
public async Task<IActionResult> Index()
{
return View(await _context.Order.ToListAsync());
}
// GET: Admin/Orders/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var order = await _context.Order
.FirstOrDefaultAsync(m => m.id == id);
if (order == null)
{
return NotFound();
}
ViewData["User_id"] = new SelectList(_context.Users, "Id", "Id", order.User_id);
return View(order);
}
// GET: Admin/Orders/Create
public IActionResult Create()
{
return View();
}
// POST: Admin/Orders/Create
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Order_Number,id,User_id,Price_total,Created,Updated")] Order order)
{
if (ModelState.IsValid)
{
_context.Add(order);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(order);
}
// GET: Admin/Orders/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var order = await _context.Order.FindAsync(id);
if (order == null)
{
return NotFound();
}
ViewData["User_id"] = new SelectList(_context.Users, "Id", "Id", order.User_id);
return View(order);
}
// POST: Admin/Orders/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Order_Number,id,User_id,Price_total,new.Created,new.Updated")] Order order)
{
if (id != order.id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(order);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!OrderExists(order.id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["User_id"] = new SelectList(_context.Users, "Id", "Id", order.User_id);
return View(order);
}
// GET: Admin/Orders/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var order = await _context.Order
.FirstOrDefaultAsync(m => m.id == id);
if (order == null)
{
return NotFound();
}
return View(order);
}
// POST: Admin/Orders/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var order = await _context.Order.FindAsync(id);
_context.Order.Remove(order);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool OrderExists(int id)
{
return _context.Order.Any(e => e.id == id);
}
}
}

View File

@ -1,172 +0,0 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Authorization;
using pwt_0x01_ng.Models;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.Identity;
using System.Collections.Generic;
namespace pwt_0x01_ng.Areas.Admin.Controllers
{
[Area("Admin")]
[Authorize(Roles = nameof(Roles.Admin) + "," + nameof(Roles.Manager))]
public class ProductController : Controller
{
IWebHostEnvironment hosting_env;
readonly DBContext dbctx;
public ProductController(DBContext dbctx, IWebHostEnvironment hosting_env){
this.dbctx = dbctx;
this.hosting_env = hosting_env;
}
public async Task <IActionResult> Select()
{
ProductViewModel product = new ProductViewModel();
product.Products = await dbctx.Product.ToListAsync();
return View(product);
}
public async Task<IActionResult> Create()
{
ProductViewModel product = new ProductViewModel();
product.Products = await dbctx.Product.ToListAsync();
ViewData["prods"] = product.Products;
return View();
}
[HttpPost]
public async Task<IActionResult> Create(Product product)
{
if (ModelState.IsValid) {
MegaUpload mega_upload = new MegaUpload(hosting_env.WebRootPath, "products", "image");
if ((product.ImageSrc = await mega_upload.DoMegaUpload(product.Image)) != string.Empty){/* all good here */};
dbctx.Product.Add(product);
await dbctx.SaveChangesAsync();
return RedirectToAction(nameof(Select));
} else {
ViewData["Message"] = "error creating Product";
return View(product);
}
}
public async Task<IActionResult> Edit(int id)
{
ProductViewModel product = new ProductViewModel();
product.Products = await dbctx.Product.ToListAsync();
ViewData["prods"] = product.Products;
Product item = dbctx.Product.Where(p_item => p_item.id == id).FirstOrDefault();
if (item != null)
{
IList<Similar> s = await dbctx.Similar.Where(p_item => p_item.prod_id == id).ToListAsync();
IList<SimilarProduct> similar = new List<SimilarProduct>();
foreach (var prod in product.Products) {
SimilarProduct sp = new SimilarProduct();
sp.id = prod.id;
sp.Selected = prod.Selected;
similar.Add(sp);
}
foreach (var s_item in s)
{
var prodpls = await dbctx.Product.Where(p_item => p_item.id == s_item.similar_prod_id).FirstOrDefaultAsync();
if(prodpls != null){
for (int i = 0; i < similar.Count; i++)
{
if(similar[i].id == prodpls.id){
similar[i].Selected = true;
}
}
}
}
item.Similar = similar;
ViewData["ImageSrc"] = new SelectList(dbctx.Product, "ImageSrc", item.ImageSrc);
return View(item);
}
else
{
return NotFound();
}
}
[HttpPost]
public async Task<IActionResult> Edit(Product product)
{
Product item = dbctx.Product.Where(p_item => p_item.id == product.id).FirstOrDefault();
if (item != null)
{
if (ModelState.IsValid) {
item.id = product.id;
item.Name = product.Name;
item.Price = product.Price;
item.Description = product.Description;
item.ImageAlt = product.ImageAlt;
MegaUpload mega_upload = new MegaUpload(hosting_env.WebRootPath, "products", "image");
if ((product.ImageSrc = await mega_upload.DoMegaUpload(product.Image)) != string.Empty){
item.ImageSrc = product.ImageSrc;
}
if (product.Similar != null) {
IList<SimilarProduct> similar = new List<SimilarProduct>();
foreach (var prod in product.Similar) {
SimilarProduct sp = new SimilarProduct();
sp.id = prod.id;
sp.Selected = prod.Selected;
similar.Add(sp);
}
if(similar.Count > 0){
foreach (var prod in similar)
{
Similar s = dbctx.Similar.Where(p_item => p_item.prod_id == item.id && p_item.similar_prod_id == prod.id).FirstOrDefault();
if(prod.Selected){
if (s == null) {
s = new Similar();
s.prod_id = item.id;
s.similar_prod_id = prod.id;
dbctx.Similar.Add(s);
}
} else {
if (s != null) {
dbctx.Similar.Remove(s);
}
}
}
}
}
await dbctx.SaveChangesAsync();
return RedirectToAction(nameof(Select));
}
var errors = ModelState.Values.SelectMany(v => v.Errors);
ViewData["Message"] = "error editing Product";
return View(item);
}
else
{
return NotFound();
}
}
public async Task <IActionResult> Delete(int id)
{
Product item = dbctx.Product.Where(p_item => p_item.id == id).FirstOrDefault();
if (item != null)
{
dbctx.Product.Remove(item);
await dbctx.SaveChangesAsync();
return RedirectToAction(nameof(Select));
}
else
{
return NotFound();
}
}
}
}

View File

@ -1,153 +0,0 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.Identity;
using Microsoft.AspNetCore.Authorization;
namespace pwt_0x01_ng.Areas.Admin.Controllers
{
[Area("Admin")]
[Authorize(Roles = nameof(Roles.Admin))]
public class UsersController : Controller
{
private readonly DBContext _context;
public UsersController(DBContext context)
{
_context = context;
}
// GET: Admin/Users
public async Task<IActionResult> Index()
{
return View(await _context.Users.ToListAsync());
}
// GET: Admin/Users/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var user = await _context.Users
.FirstOrDefaultAsync(m => m.Id == id);
if (user == null)
{
return NotFound();
}
return View(user);
}
// GET: Admin/Users/Create
public IActionResult Create()
{
return View();
}
// POST: Admin/Users/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Name,LastName,Id,UserName,NormalizedUserName,Email,NormalizedEmail,EmailConfirmed,PasswordHash,SecurityStamp,ConcurrencyStamp,TwoFactorEnabled,LockoutEnd,LockoutEnabled,AccessFailedCount")] User user)
{
if (ModelState.IsValid)
{
_context.Add(user);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(user);
}
// GET: Admin/Users/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var user = await _context.Users.FindAsync(id);
if (user == null)
{
return NotFound();
}
return View(user);
}
// POST: Admin/Users/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Name,LastName,Id,UserName,NormalizedUserName,Email,NormalizedEmail,EmailConfirmed,PasswordHash,SecurityStamp,ConcurrencyStamp,TwoFactorEnabled,LockoutEnd,LockoutEnabled,AccessFailedCount")] User user)
{
if (id != user.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(user);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!UserExists(user.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(user);
}
// GET: Admin/Users/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var user = await _context.Users
.FirstOrDefaultAsync(m => m.Id == id);
if (user == null)
{
return NotFound();
}
return View(user);
}
// POST: Admin/Users/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var user = await _context.Users.FindAsync(id);
_context.Users.Remove(user);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool UserExists(int id)
{
return _context.Users.Any(e => e.Id == id);
}
}
}

View File

@ -1,7 +1,6 @@
@using pwt_0x01_ng.Areas.Admin.Controllers;
@model Carousel
@{
ViewData["Title"] = "Carousel Creation";
ViewData["Title"] = "Carousel Creation";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
@ -10,8 +9,3 @@
@{ViewBag.Action = "Create";}
@await Html.PartialAsync("PartialForm_EditCreate", Model)
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script defer src="~/js/validation/file_type.js"></script>
}

View File

@ -1,7 +1,6 @@
@using pwt_0x01_ng.Areas.Admin.Controllers;
@model Carousel
@{
ViewData["Title"] = "Carousel Editing";
ViewData["Title"] = "Carousel Editing";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
@ -9,9 +8,4 @@
<p>Edit carousel item.</p>
@{ViewBag.Action = "Edit";}
<partial name="PartialForm_EditCreate" model="Model"/>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script defer src="~/js/validation/file_type.js"></script>
}
<partial name="PartialForm_EditCreate" model="Model">

View File

@ -1,41 +1,36 @@
@using pwt_0x01_ng.Areas.Admin.Controllers;
@model Carousel
@{
if((!String.IsNullOrEmpty(ViewBag.Action))||(!String.IsNullOrWhiteSpace(ViewBag.Action)))
{
<div class="row">
<form asp-action="@ViewBag.Action" enctype="multipart/form-data" method="post">
<div class="form-group col-sm-4">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@{if (@ViewBag.Action == nameof(CarouselController.Edit)){
<input type="hidden" asp-for="@Model.id" class="form-control" aria-describedby="carousel id edit">
}}
<div class="form-group">
<label asp-for="@Model.DataTarget"></label>
<input asp-for="@Model.DataTarget" class="form-control" aria-describedby="css selector id of the image" placeholder="Data Target">
<span asp-validation-for="@Model.DataTarget" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="@Model.Image"></label>
<input id="file" asp-for="@Model.Image" accept="image/*" class="form-inline" aria-describedby="the image">
<span asp-validation-for="@Model.Image" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="@Model.ImageAlt"></label>
<input asp-for="@Model.ImageAlt" class="form-control" aria-describedby="image alt text" placeholder="Image alt">
<span asp-validation-for="@Model.ImageAlt" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="@Model.CarouselContent"></label>
<textarea asp-for="@Model.CarouselContent" class="form-control" aria-describedby="image description" placeholder="Image description"></textarea>
<span asp-validation-for="@Model.CarouselContent" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
}
else {
<h2>Error: Action is not set</h2>
}
if((!String.IsNullOrEmpty(ViewBag.Action))||(!String.IsNullOrWhiteSpace(ViewBag.Action)))
{
<div class="row">
<form asp-action="@ViewBag.Action" enctype="multipart/form-data" method="post">
<div class="form-group col-sm-4">
<div class="form-group">
<label asp-for="@Model.id"></label>
<input asp-for="@Model.id" class="form-control" id="inputCarousel" aria-describedby="carouselHelp" placeholder="id">
</div>
<div class="form-group">
<label asp-for="@Model.DataTarget"></label>
<input asp-for="@Model.DataTarget" class="form-control" id="inputCarousel" aria-describedby="carouselHelp" placeholder="Data Target">
</div>
<div class="form-group">
<label asp-for="@Model.Image"></label>
<input asp-for="@Model.Image" accept="image/*" class="form-inline" id="inputCarousel" aria-describedby="carouselHelp">
</div>
<div class="form-group">
<label asp-for="@Model.ImageAlt"></label>
<input asp-for="@Model.ImageAlt" class="form-control" id="inputCarousel" aria-describedby="carouselHelp" placeholder="Image alt">
</div>
<div class="form-group">
<label asp-for="@Model.CarouselContent"></label>
<input asp-for="@Model.CarouselContent" class="form-control" id="inputCarousel" aria-describedby="carouselHelp" placeholder="Image description">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
}
else {
<h2>Error: Action is not set</h2>
}
}

View File

@ -1,6 +1,6 @@
@model CarouselViewModel
@{
ViewData["Title"] = "Carousel Select";
ViewData["Title"] = "Carousel Select";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
@ -11,35 +11,40 @@
<br/><br/>
@{
if (Model?.Carousels != null && Model.Carousels.Count > 0) {
<table id="carousel_table" class="table table-responsive table-striped table-bordered">
<tr>
<th class="col-sm-1">@Html.DisplayNameFor(model => model.Carousels[0].id)</th>
<th class="col-sm-1">@Html.DisplayNameFor(model => model.Carousels[0].DataTarget)</th>
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Carousels[0].ImageSrc)</th>
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Carousels[0].ImageAlt)</th>
<th class="col-sm-4">@Html.DisplayNameFor(model => model.Carousels[0].CarouselContent)</th>
<th class="col-sm-1">Edit</th>
<th class="col-sm-1">Delete</th>
</tr>
@{
foreach (var carousel_item in Model.Carousels)
{
<tr>
<td class="col-sm-1">@carousel_item.id</td>
<td class="col-sm-1">@carousel_item.DataTarget</td>
<td class="col-sm-2">@carousel_item.ImageSrc</td>
<td class="col-sm-2">@carousel_item.ImageAlt</td>
<td class="col-sm-4">@carousel_item.CarouselContent</td>
<td class="col-sm-1"><a asp-action="Edit" asp-route-id="@carousel_item.id">Edit</a></td>
<td class="col-sm-1"><a asp-action="Delete" asp-route-id="@carousel_item.id" onclick="return item_deletion_confirmation();">Delete</a></td>
</tr>
}
}
</table>
}
else
{
<h2>Carousel is empty</h2>
}
if (Model?.Carousels != null && Model.Carousels.Count > 0) {
<table style="width:100%">
<tr>
<th class="col-sm-1">@Html.DisplayNameFor(model => model.Carousels[0].id)</th>
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Carousels[0].DataTarget)</th>
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Carousels[0].ImageSrc)</th>
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Carousels[0].ImageAlt)</th>
<th class="col-sm-4">@Html.DisplayNameFor(model => model.Carousels[0].CarouselContent)</th>
<th class="col-sm-1">Edit</th>
<th class="col-sm-1">Delete</th>
</tr>
@{
foreach (var carousel_item in Model.Carousels)
{
<tr>
<td class="col-sm-1">@carousel_item.id</td>
<td class="col-sm-2">@carousel_item.DataTarget</td>
<td class="col-sm-2">@carousel_item.ImageSrc</td>
<td class="col-sm-2">@carousel_item.ImageAlt</td>
<td class="col-sm-4">@carousel_item.CarouselContent</td>
<td class="col-sm-2"><a asp-action="Edit" asp-route-id="@carousel_item.id">Edit</a></td>
<td class="col-sm-2"><a asp-action="Delete" asp-route-id="@carousel_item.id" onclick="return c_item_deletion_confirmation();">Delete</a></td>
</tr>
}
}
</table>
}
else
{
<h2>Carousel is empty</h2>
}
}
@section Scripts
{
<script src="~/js/ultimate_script.js"></script>
}

View File

@ -1,42 +0,0 @@
@model pwt_0x01_ng.Models.OrderItem
@{
ViewData["Title"] = "Create";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<h4>OrderItem</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Order_id" class="control-label"></label>
<select asp-for="Order_id" class ="form-control" asp-items="ViewBag.Order_id"></select>
</div>
<div class="form-group">
<label asp-for="Product_id" class="control-label"></label>
<select asp-for="Product_id" class ="form-control" asp-items="ViewBag.Product_id"></select>
</div>
<div class="form-group">
<label asp-for="Amount" class="control-label"></label>
<input asp-for="Amount" class="form-control" />
<span asp-validation-for="Amount" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>

View File

@ -1,57 +0,0 @@
@model pwt_0x01_ng.Models.OrderItem
@{
ViewData["Title"] = "Delete";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>OrderItem</h4>
<hr />
<dl class="row">
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Amount)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Amount)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Price)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Price)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Order)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Order.Order_Number)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Product)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Product.Description)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Created)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Created)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Updated)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Updated)
</dd>
</dl>
<form asp-action="Delete">
<input type="hidden" asp-for="id" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-action="Index">Back to List</a>
</form>
</div>

View File

@ -1,54 +0,0 @@
@model pwt_0x01_ng.Models.OrderItem
@{
ViewData["Title"] = "Details";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<div>
<h4>OrderItem</h4>
<hr />
<dl class="row">
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Amount)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Amount)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Price)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Price)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Order)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Order.Order_Number)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Product)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Product.Description)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Created)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Created)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Updated)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Updated)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>

View File

@ -1,45 +0,0 @@
@model pwt_0x01_ng.Models.OrderItem
@{
ViewData["Title"] = "Edit";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<h4>OrderItem</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Order_id" class="control-label"></label>
<select asp-for="Order_id" class="form-control" asp-items="ViewBag.Order_id"></select>
<span asp-validation-for="Order_id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Product_id" class="control-label"></label>
<select asp-for="Product_id" class="form-control" asp-items="ViewBag.Product_id"></select>
<span asp-validation-for="Product_id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Amount" class="control-label"></label>
<input asp-for="Amount" class="form-control" />
<span asp-validation-for="Amount" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<input type="hidden" asp-for="id" />
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>

View File

@ -1,65 +0,0 @@
@model IEnumerable<pwt_0x01_ng.Models.OrderItem>
@{
ViewData["Title"] = "OrderItem";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table table-responsive table-striped table-bordered">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Amount)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Order)
</th>
<th>
@Html.DisplayNameFor(model => model.Product)
</th>
<th>
@Html.DisplayNameFor(model => model.Created)
</th>
<th>
@Html.DisplayNameFor(model => model.Updated)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Amount)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Order.Order_Number)
</td>
<td>
@Html.DisplayFor(modelItem => item.Product.Description)
</td>
<td>
@Html.DisplayFor(modelItem => item.Created)
</td>
<td>
@Html.DisplayFor(modelItem => item.Updated)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.id">Delete</a>
</td>
</tr>
}
</tbody>
</table>

View File

@ -1,34 +0,0 @@
@model pwt_0x01_ng.Models.Order
@{
ViewData["Title"] = "Create";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<h4>Order</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Order_Number" class="control-label"></label>
<input asp-for="Order_Number" class="form-control" />
<span asp-validation-for="Order_Number" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="User_id" class="control-label"></label>
<input asp-for="User_id" class="form-control" />
<span asp-validation-for="User_id" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>

View File

@ -1,51 +0,0 @@
@model pwt_0x01_ng.Models.Order
@{
ViewData["Title"] = "Delete";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Order</h4>
<hr />
<dl class="row">
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Order_Number)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Order_Number)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.User_id)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.User_id)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Price_total)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Price_total)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Created)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Created)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Updated)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Updated)
</dd>
</dl>
<form asp-action="Delete">
<input type="hidden" asp-for="id" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-action="Index">Back to List</a>
</form>
</div>

View File

@ -1,48 +0,0 @@
@model pwt_0x01_ng.Models.Order
@{
ViewData["Title"] = "Details";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<div>
<h4>Order</h4>
<hr />
<dl class="row">
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Order_Number)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Order_Number)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.User_id)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.User_id)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Price_total)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Price_total)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Created)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Created)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Updated)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Updated)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>

View File

@ -1,40 +0,0 @@
@model pwt_0x01_ng.Models.Order
@{
ViewData["Title"] = "Edit";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<h4>Order</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Order_Number" class="control-label"></label>
<input asp-for="Order_Number" class="form-control" />
<span asp-validation-for="Order_Number" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="User_id" class="control-label"></label>
<input asp-for="User_id" class="form-control" />
<span asp-validation-for="User_id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price_total" class="control-label"></label>
<input asp-for="Price_total" class="form-control" />
<span asp-validation-for="Price_total" class="text-danger"></span>
</div>
<input type="hidden" asp-for="id" />
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>

View File

@ -1,58 +0,0 @@
@model IEnumerable<pwt_0x01_ng.Models.Order>
@{
ViewData["Title"] = "Order Index";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table table-responsive table-striped table-bordered">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Order_Number)
</th>
<th>
@Html.DisplayNameFor(model => model.User_id)
</th>
<th>
@Html.DisplayNameFor(model => model.Price_total)
</th>
<th>
@Html.DisplayNameFor(model => model.Created)
</th>
<th>
@Html.DisplayNameFor(model => model.Updated)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Order_Number)
</td>
<td>
@Html.DisplayFor(modelItem => item.User_id)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price_total)
</td>
<td>
@Html.DisplayFor(modelItem => item.Created)
</td>
<td>
@Html.DisplayFor(modelItem => item.Updated)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.id">Delete</a>
</td>
</tr>
}
</tbody>
</table>

View File

@ -1,16 +0,0 @@
@model Product
@{
ViewData["Title"] = "Product - Create";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<p>Create new item.</p>
@{ViewBag.Action = "Create";}
@await Html.PartialAsync("edit-create_part", Model)
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script defer src="~/js/validation/file_type.js"></script>
}

View File

@ -1,16 +0,0 @@
@model Product
@{
ViewData["Title"] = "Product - Edit";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<p>Edit product.</p>
@{ViewBag.Action = "Edit";}
<partial name="edit-create_part" model="Model"/>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script defer src="~/js/validation/file_type.js"></script>
}

View File

@ -1,46 +0,0 @@
@model ProductViewModel
@{
ViewData["Title"] = "Products";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<p>All product data.</p>
<a asp-action="Create">Create new item</a>
<br/><br/>
@{
if (Model?.Products != null && Model.Products.Count > 0) {
<table id="product_table" class="table table-responsive table-striped table-bordered">
<tr>
<th class="col-sm">@Html.DisplayNameFor(model => model.Products[0].id)</th>
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Products[0].Name)</th>
<th class="col-sm-1">@Html.DisplayNameFor(model => model.Products[0].Price)</th>
<th class="col-sm-3">@Html.DisplayNameFor(model => model.Products[0].Description)</th>
<th class="col-sm-3">@Html.DisplayNameFor(model => model.Products[0].ImageSrc)</th>
<th class="col-sm-2">@Html.DisplayNameFor(model => model.Products[0].ImageAlt)</th>
<th class="col-sm">Edit</th>
<th class="col-sm">Delete</th>
</tr>
@{
foreach (var item in Model.Products)
{
<tr>
<td class="col-sm">@item.id</td>
<td class="col-sm-2">@item.Name</td>
<td class="col-sm-1">@item.Price</td>
<td class="col-sm-3">@item.Description</td>
<td class="col-sm-3">@item.ImageSrc</td>
<td class="col-sm-2">@item.ImageAlt</td>
<td class="col-sm"><a asp-action="Edit" asp-route-id="@item.id">Edit</a></td>
<td class="col-sm"><a asp-action="Delete" asp-route-id="@item.id" onclick="return item_deletion_confirmation();">Delete</a></td>
</tr>
}
}
</table>
}
else
{
<h2>No products to show</h2>
}
}

View File

@ -1,79 +0,0 @@
@using pwt_0x01_ng.Areas.Admin.Controllers;
@model Product
@{
IList<Product> products;
IList<SimilarProduct> similar;
products = (IList<Product>)ViewData["prods"];
similar = new List<SimilarProduct>();
if((!String.IsNullOrEmpty(ViewBag.Action))||(!String.IsNullOrWhiteSpace(ViewBag.Action)))
{
<div class="row">
<form asp-action="@ViewBag.Action" enctype="multipart/form-data" method="post">
<div class="form-group col-sm-4">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
@{
if (@ViewBag.Action == nameof(ProductController.Edit)){
<input type="hidden" asp-for="@Model.id" class="form-control">
}
}
<div class="form-group">
<label asp-for="@Model.Name"></label>
<input asp-for="@Model.Name" class="form-control" aria-describedby="product name" placeholder="product name">
<span asp-validation-for="@Model.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="@Model.Price"></label>
<input asp-for="@Model.Price" class="form-control" aria-describedby="product price" placeholder="price">
<span asp-validation-for="@Model.Price" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="@Model.Description"></label>
<input asp-for="@Model.Description" class="form-control" aria-describedby="product description" placeholder="description">
<span asp-validation-for="@Model.Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="@Model.Image"></label>
<input id="file" asp-for="@Model.Image" accept="image/*" class="form-inline" aria-describedby="product image">
<span asp-validation-for="@Model.Image" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="@Model.ImageAlt"></label>
<input asp-for="@Model.ImageAlt" class="form-control" aria-describedby="product image alt text" placeholder="Image alt">
<span asp-validation-for="@Model.ImageAlt" class="text-danger"></span>
</div>
@{
if(@Model != null && products != null && products.Count > 0){
<div class="form-group form-check">
<div>
<label>similar products</label>
</div>
@if(@Model.Similar != null){
similar = @Model.Similar;
}
@for(int i = 0; i < products.Count; i++){
@if(products.ElementAt(i).id != @Model.id){
<label class="form-check-label checkbox-inline">@products.ElementAt(i).Name</label>
@if(similar[i].Selected){
<input asp-for="@Model.Similar[i].Selected" type="checkbox" checked>
<input asp-for="@Model.Similar[i].id" type="hidden">
} else {
<input asp-for="@Model.Similar[i].Selected" type="checkbox">
<input asp-for="@Model.Similar[i].id" type="hidden">
}
} else {
<input asp-for="@Model.Similar[i].Selected" type="checkbox" hidden>
<input asp-for="@Model.Similar[i].id" type="hidden">
}
}
</div>
}
}
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
}
else {
<h2>Error: Action is not set</h2>
}
}

View File

@ -1,104 +0,0 @@
@model pwt_0x01_ng.Models.Identity.User
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<h4>User</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LastName" class="control-label"></label>
<input asp-for="LastName" class="form-control" />
<span asp-validation-for="LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="UserName" class="control-label"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NormalizedUserName" class="control-label"></label>
<input asp-for="NormalizedUserName" class="form-control" />
<span asp-validation-for="NormalizedUserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NormalizedEmail" class="control-label"></label>
<input asp-for="NormalizedEmail" class="form-control" />
<span asp-validation-for="NormalizedEmail" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input asp-for="EmailConfirmed" /> @Html.DisplayNameFor(model => model.EmailConfirmed)
</label>
</div>
</div>
<div class="form-group">
<label asp-for="PasswordHash" class="control-label"></label>
<input asp-for="PasswordHash" class="form-control" />
<span asp-validation-for="PasswordHash" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="SecurityStamp" class="control-label"></label>
<input asp-for="SecurityStamp" class="form-control" />
<span asp-validation-for="SecurityStamp" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ConcurrencyStamp" class="control-label"></label>
<input asp-for="ConcurrencyStamp" class="form-control" />
<span asp-validation-for="ConcurrencyStamp" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input asp-for="TwoFactorEnabled" /> @Html.DisplayNameFor(model => model.TwoFactorEnabled)
</label>
</div>
</div>
<div class="form-group">
<label asp-for="LockoutEnd" class="control-label"></label>
<input asp-for="LockoutEnd" class="form-control" />
<span asp-validation-for="LockoutEnd" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input asp-for="LockoutEnabled" /> @Html.DisplayNameFor(model => model.LockoutEnabled)
</label>
</div>
</div>
<div class="form-group">
<label asp-for="AccessFailedCount" class="control-label"></label>
<input asp-for="AccessFailedCount" class="form-control" />
<span asp-validation-for="AccessFailedCount" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

View File

@ -1,105 +0,0 @@
@model pwt_0x01_ng.Models.Identity.User
@{
ViewData["Title"] = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>User</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.LastName)
</dt>
<dd>
@Html.DisplayFor(model => model.LastName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.UserName)
</dt>
<dd>
@Html.DisplayFor(model => model.UserName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.NormalizedUserName)
</dt>
<dd>
@Html.DisplayFor(model => model.NormalizedUserName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Email)
</dt>
<dd>
@Html.DisplayFor(model => model.Email)
</dd>
<dt>
@Html.DisplayNameFor(model => model.NormalizedEmail)
</dt>
<dd>
@Html.DisplayFor(model => model.NormalizedEmail)
</dd>
<dt>
@Html.DisplayNameFor(model => model.EmailConfirmed)
</dt>
<dd>
@Html.DisplayFor(model => model.EmailConfirmed)
</dd>
<dt>
@Html.DisplayNameFor(model => model.PasswordHash)
</dt>
<dd>
@Html.DisplayFor(model => model.PasswordHash)
</dd>
<dt>
@Html.DisplayNameFor(model => model.SecurityStamp)
</dt>
<dd>
@Html.DisplayFor(model => model.SecurityStamp)
</dd>
<dt>
@Html.DisplayNameFor(model => model.ConcurrencyStamp)
</dt>
<dd>
@Html.DisplayFor(model => model.ConcurrencyStamp)
</dd>
<dt>
@Html.DisplayNameFor(model => model.TwoFactorEnabled)
</dt>
<dd>
@Html.DisplayFor(model => model.TwoFactorEnabled)
</dd>
<dt>
@Html.DisplayNameFor(model => model.LockoutEnd)
</dt>
<dd>
@Html.DisplayFor(model => model.LockoutEnd)
</dd>
<dt>
@Html.DisplayNameFor(model => model.LockoutEnabled)
</dt>
<dd>
@Html.DisplayFor(model => model.LockoutEnabled)
</dd>
<dt>
@Html.DisplayNameFor(model => model.AccessFailedCount)
</dt>
<dd>
@Html.DisplayFor(model => model.AccessFailedCount)
</dd>
</dl>
<form asp-action="Delete">
<input type="hidden" asp-for="Id" />
<input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-action="Index">Back to List</a>
</form>
</div>

View File

@ -1,102 +0,0 @@
@model pwt_0x01_ng.Models.Identity.User
@{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>User</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.LastName)
</dt>
<dd>
@Html.DisplayFor(model => model.LastName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.UserName)
</dt>
<dd>
@Html.DisplayFor(model => model.UserName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.NormalizedUserName)
</dt>
<dd>
@Html.DisplayFor(model => model.NormalizedUserName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Email)
</dt>
<dd>
@Html.DisplayFor(model => model.Email)
</dd>
<dt>
@Html.DisplayNameFor(model => model.NormalizedEmail)
</dt>
<dd>
@Html.DisplayFor(model => model.NormalizedEmail)
</dd>
<dt>
@Html.DisplayNameFor(model => model.EmailConfirmed)
</dt>
<dd>
@Html.DisplayFor(model => model.EmailConfirmed)
</dd>
<dt>
@Html.DisplayNameFor(model => model.PasswordHash)
</dt>
<dd>
@Html.DisplayFor(model => model.PasswordHash)
</dd>
<dt>
@Html.DisplayNameFor(model => model.SecurityStamp)
</dt>
<dd>
@Html.DisplayFor(model => model.SecurityStamp)
</dd>
<dt>
@Html.DisplayNameFor(model => model.ConcurrencyStamp)
</dt>
<dd>
@Html.DisplayFor(model => model.ConcurrencyStamp)
</dd>>
<dt>
@Html.DisplayNameFor(model => model.TwoFactorEnabled)
</dt>
<dd>
@Html.DisplayFor(model => model.TwoFactorEnabled)
</dd>
<dt>
@Html.DisplayNameFor(model => model.LockoutEnd)
</dt>
<dd>
@Html.DisplayFor(model => model.LockoutEnd)
</dd>
<dt>
@Html.DisplayNameFor(model => model.LockoutEnabled)
</dt>
<dd>
@Html.DisplayFor(model => model.LockoutEnabled)
</dd>
<dt>
@Html.DisplayNameFor(model => model.AccessFailedCount)
</dt>
<dd>
@Html.DisplayFor(model => model.AccessFailedCount)
</dd>
</dl>
</div>
<div>
<a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
<a asp-action="Index">Back to List</a>
</div>

View File

@ -1,117 +0,0 @@
@model pwt_0x01_ng.Models.Identity.User
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>User</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="LastName" class="control-label"></label>
<input asp-for="LastName" class="form-control" />
<span asp-validation-for="LastName" class="text-danger"></span>
</div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="UserName" class="control-label"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NormalizedUserName" class="control-label"></label>
<input asp-for="NormalizedUserName" class="form-control" />
<span asp-validation-for="NormalizedUserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="NormalizedEmail" class="control-label"></label>
<input asp-for="NormalizedEmail" class="form-control" />
<span asp-validation-for="NormalizedEmail" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input asp-for="EmailConfirmed" /> @Html.DisplayNameFor(model => model.EmailConfirmed)
</label>
</div>
</div>
<div class="form-group">
<label asp-for="PasswordHash" class="control-label"></label>
<input asp-for="PasswordHash" class="form-control" />
<span asp-validation-for="PasswordHash" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="SecurityStamp" class="control-label"></label>
<input asp-for="SecurityStamp" class="form-control" />
<span asp-validation-for="SecurityStamp" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ConcurrencyStamp" class="control-label"></label>
<input asp-for="ConcurrencyStamp" class="form-control" />
<span asp-validation-for="ConcurrencyStamp" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PhoneNumber" class="control-label"></label>
<input asp-for="PhoneNumber" class="form-control" />
<span asp-validation-for="PhoneNumber" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input asp-for="PhoneNumberConfirmed" /> @Html.DisplayNameFor(model => model.PhoneNumberConfirmed)
</label>
</div>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input asp-for="TwoFactorEnabled" /> @Html.DisplayNameFor(model => model.TwoFactorEnabled)
</label>
</div>
</div>
<div class="form-group">
<label asp-for="LockoutEnd" class="control-label"></label>
<input asp-for="LockoutEnd" class="form-control" />
<span asp-validation-for="LockoutEnd" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input asp-for="LockoutEnabled" /> @Html.DisplayNameFor(model => model.LockoutEnabled)
</label>
</div>
</div>
<div class="form-group">
<label asp-for="AccessFailedCount" class="control-label"></label>
<input asp-for="AccessFailedCount" class="form-control" />
<span asp-validation-for="AccessFailedCount" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

View File

@ -1,113 +0,0 @@
@model IEnumerable<pwt_0x01_ng.Models.Identity.User>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table table-responsive table-striped table-bordered">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.LastName)
</th>
<th>
@Html.DisplayNameFor(model => model.UserName)
</th>
<th>
@Html.DisplayNameFor(model => model.NormalizedUserName)
</th>
<th>
@Html.DisplayNameFor(model => model.Email)
</th>
<th>
@Html.DisplayNameFor(model => model.NormalizedEmail)
</th>
<th>
@Html.DisplayNameFor(model => model.EmailConfirmed)
</th>
<th>
@Html.DisplayNameFor(model => model.PasswordHash)
</th>
<th>
@Html.DisplayNameFor(model => model.SecurityStamp)
</th>
<th>
@Html.DisplayNameFor(model => model.ConcurrencyStamp)
</th>
<th>
@Html.DisplayNameFor(model => model.TwoFactorEnabled)
</th>
<th>
@Html.DisplayNameFor(model => model.LockoutEnd)
</th>
<th>
@Html.DisplayNameFor(model => model.LockoutEnabled)
</th>
<th>
@Html.DisplayNameFor(model => model.AccessFailedCount)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
@Html.DisplayFor(modelItem => item.NormalizedUserName)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
@Html.DisplayFor(modelItem => item.NormalizedEmail)
</td>
<td>
@Html.DisplayFor(modelItem => item.EmailConfirmed)
</td>
<td>
@Html.DisplayFor(modelItem => item.PasswordHash)
</td>
<td>
@Html.DisplayFor(modelItem => item.SecurityStamp)
</td>
<td>
@Html.DisplayFor(modelItem => item.ConcurrencyStamp)
</td>
<td>
@Html.DisplayFor(modelItem => item.TwoFactorEnabled)
</td>
<td>
@Html.DisplayFor(modelItem => item.LockoutEnd)
</td>
<td>
@Html.DisplayFor(modelItem => item.LockoutEnabled)
</td>
<td>
@Html.DisplayFor(modelItem => item.AccessFailedCount)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>

View File

@ -1,3 +1,3 @@
@{
Layout = "_Layout";
Layout = "_Layout";
}

View File

@ -1,118 +0,0 @@
using pwt_0x01_ng.Controllers;
using pwt_0x01_ng.Models;
using pwt_0x01_ng.Models.ApplicationServices;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace pwt_0x01_ng.Areas.Customer.Controllers
{
[Area("Customer")]
[Authorize(Roles = nameof(Roles.Customer))]
public class CustomerOrderNotCartController : Controller
{
const string s_price_total = "Price_total";
const string s_order_items = "OrderItems";
ISecurityApplicationService isas;
DBContext ctx;
public CustomerOrderNotCartController(ISecurityApplicationService isas, DBContext ctx)
{
this.isas = isas;
this.ctx = ctx;
}
[HttpPost]
public int AddOrderItemsToSession(int? Product_id)
{
int price_total = 0;
if (HttpContext.Session.IsAvailable)
{
price_total = HttpContext.Session.GetInt32(s_price_total).GetValueOrDefault();
}
Product product = ctx.Product.Where(prod => prod.id == Product_id).FirstOrDefault();
if (product != null)
{
OrderItem order_item = new OrderItem()
{
Product_id = product.id,
Product = product,
Amount = 1,
Price = product.Price
};
if (HttpContext.Session.IsAvailable)
{
List<OrderItem> orderItems = HttpContext.Session.GetObject<List<OrderItem>>(s_order_items);
OrderItem orderItemInSession = null;
if (orderItems != null){
orderItemInSession = orderItems.Find(oi => oi.Product_id == order_item.Product_id);
}
else
orderItems = new List<OrderItem>();
if (orderItemInSession != null)
{
++orderItemInSession.Amount;
orderItemInSession.Price += order_item.Product.Price;
}
else
{
orderItems.Add(order_item);
}
HttpContext.Session.SetObject(s_order_items, orderItems);
price_total += order_item.Product.Price;
HttpContext.Session.SetInt32(s_price_total, price_total);
}
}
return price_total;
}
public async Task<IActionResult> ApproveOrderInSession()
{
if (HttpContext.Session.IsAvailable)
{
int price_total = 0;
List<OrderItem> order_items = HttpContext.Session.GetObject<List<OrderItem>>(s_order_items);
if (order_items != null)
{
foreach (OrderItem order_item in order_items)
{
price_total += order_item.Product.Price * order_item.Amount;
order_item.Product = null;
}
User currentUser = await isas.gimme_current_user(User);
Order order = new Order()
{
Order_Number = Convert.ToBase64String(Guid.NewGuid().ToByteArray()),
Price_total = price_total,
OrderItems = order_items,
User_id = currentUser.Id
};
await ctx.AddAsync(order);
await ctx.SaveChangesAsync();
HttpContext.Session.Remove(s_order_items);
HttpContext.Session.Remove(s_price_total);
return RedirectToAction(nameof(CustomerOrdersController.Index), nameof(CustomerOrdersController).Replace("Controller", ""), new { Area = nameof(Customer) });
}
}
return RedirectToAction(nameof(HomeController.Index), nameof(HomeController).Replace("Controller", ""), new { Area = "" });
}
}
}

View File

@ -1,49 +0,0 @@
using pwt_0x01_ng.Models;
using pwt_0x01_ng.Models.ApplicationServices;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace pwt_0x01_ng.Areas.Customer.Controllers
{
[Area("Customer")]
[Authorize(Roles = nameof(Roles.Customer))]
public class CustomerOrdersController : Controller
{
ISecurityApplicationService isas;
DBContext ctx;
public CustomerOrdersController(ISecurityApplicationService isas, DBContext ctx)
{
this.isas = isas;
this.ctx = ctx;
}
public async Task<IActionResult> Index()
{
if (User.Identity.IsAuthenticated)
{
User currentUser = await isas.gimme_current_user(User);
if (currentUser != null)
{
IList<Order> userOrders = await this.ctx.Order
.Where(or => or.User_id == currentUser.Id)
.Include(o => o.OrderItems)
.ThenInclude(oi => oi.Product)
.ToListAsync();
string uname = currentUser.username;
ViewData["uname"] = uname;
return View(userOrders);
}
}
return NotFound();
}
}
}

View File

@ -1,62 +0,0 @@
@model IList<Order>;
@{
ViewData["Title"] = "My Orders";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
@{
if (Model != null && Model != null && Model.Count > 0)
{
foreach (var item in Model)
{
<table id="myorders_table" class="table table-responsive table-striped table-bordered">
<tr>
<th class="col-sm-1">@nameof(Order.id)</th>
<th class="col-sm-2">@nameof(Order.Order_Number)</th>
<th class="col-sm-2">@nameof(Order.Price_total)</th>
<th class="col-sm-2">@nameof(Order.Created)</th>
<th class="col-sm-2">@nameof(Order.Updated)</th>
<th class="col-sm-3">username</th>
</tr>
<tr>
<td class="col-sm-1">@item.id</td>
<td class="col-sm-2">@item.Order_Number</td>
<td class="col-sm-2">@item.Price_total</td>
<td class="col-sm-2">@item.Created</td>
<td class="col-sm-2">@item.Updated</td>
<td class="col-sm-3">@ViewData["uname"]</td>
</tr>
</table>
<details id="details_summary">
<summary class="btn-link">View Details</summary>
<div>
<h4>Order Items</h4>
<table id="order_details_table" class="table table-responsive table-bordered">
<tr>
<th class="col-sm-3">@nameof(Product.Name)</th>
<th class="col-sm-1">@nameof(OrderItem.Amount)</th>
<th class="col-sm-1">@nameof(OrderItem.Price)</th>
</tr>
@{
foreach (var order_items_item in item.OrderItems)
{
<tr>
<td class="col-sm-3">@order_items_item.Product.Name</td>
<td class="col-sm-1">@order_items_item.Amount</td>
<td class="col-sm-1">@order_items_item.Price</td>
</tr>
}
}
</table>
</div>
</details>
}
}
else
{
<h2>Orders are empty!</h2>
}
}

View File

@ -1,3 +0,0 @@
@using pwt_0x01_ng
@using pwt_0x01_ng.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -1,3 +0,0 @@
@{
Layout = "_Layout";
}

View File

@ -1,76 +0,0 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using pwt_0x01_ng.Models.ApplicationServices;
using pwt_0x01_ng.Controllers;
using pwt_0x01_ng.Models;
namespace pwt_0x01_ng.Areas.Security.Controllers
{
[Area("Security")]
[AllowAnonymous]
public class AccountController : Controller
{
private ISecurityApplicationService isas;
public AccountController(ISecurityApplicationService isas){
this.isas = isas;
}
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel lvm)
{
lvm.login_failed = false;
if(ModelState.IsValid){
bool login_success = await isas.login(lvm);
if(login_success){
return RedirectToAction(nameof(HomeController.Index), nameof(HomeController).Replace("Controller", String.Empty), new {area = ""});
} else {
lvm.login_failed = true;
}
}
return View(lvm);
}
public IActionResult Logout()
{
isas.logout();
return RedirectToRoute(new { action = nameof(HomeController.Index), controller = nameof(HomeController).Replace("Controller", String.Empty), area="" });
}
public IActionResult Register()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Register(RegisterViewModel rvm)
{
string[] errors = null;
if(ModelState.IsValid){
errors = await isas.register(rvm, Models.Identity.Roles.Customer);
if(errors == null){
var lvm = new LoginViewModel(){username = rvm.username, password = rvm.password, login_failed = false};
return await Login(lvm);
}
Console.WriteLine("error registering user {" + rvm.username + "," + rvm.email + "," + rvm.password + "}.");
}
string err = "";
for (int i = 0; i < ModelState.Values.Count(); i++){
for (int j = 0; j < ModelState.Values.ElementAt(i).Errors.Count(); j++){
err += "\n " + ModelState.Values.ElementAt(i).Errors.ElementAt(j).ToString();
}
}
Console.WriteLine("ModelState errors: " + err);
ViewData["Message"] = "error registering an account => \n" + err;
return View();
}
}
}

View File

@ -1,57 +0,0 @@
@using pwt_0x01_ng.Areas.Admin.Controllers;
@model LoginViewModel
@{
ViewData["Title"] = "Login";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<div class="container">
<div class="login">
<h3>Login or <a href="/Security/Account/Register">Sign up</a></h3>
<div class="row row-xs-offset-1 row-sm-offset-2">
<div class="col-xs-2 col-sm-2">
<a href="#" class="btn btn-lg btn-block btn-facebook" data-toggle="tooltip" data-placement="top" title="Facebook">
<i class="fa fa-facebook fa-1x"></i>
</a>
</div>
<div class="col-xs-2 col-sm-2">
<a href="#" class="btn btn-lg btn-block btn-twitter" data-toggle="tooltip" data-placement="top" title="Twitter">
<i class="fa fa-twitter fa-1x"></i>
</a>
</div>
<div class="col-xs-2 col-sm-2">
<a href="#" class="btn btn-lg btn-block btn-github" data-toggle="tooltip" data-placement="top" title="GitHub">
<i class="fa fa-github fa-1x"></i>
</a>
</div>
</div>
<br>
<div class="row row-sm-offset-3">
<div class="col-xs-12 col-sm-6"><hr></div>
</div>
<div class="row row-sm-offset-3">
<div class="form-group col-xs-12 col-sm-6">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<form class="loginForm" action="" enctype="multipart/form-data" method="post">
<span asp-validation-for="@Model.username" class="text-danger"></span>
<div class="input-group">
<span class="input-group-addon"><span class="fa fa-user"></span></span>
<input asp-for="@Model.username" type="text" class="form-control" name="username" placeholder="Username">
</div>
<br>
<span asp-validation-for="@Model.password" class="text-danger"></span>
<div class="input-group">
<span class="input-group-addon"><span class="fa fa-key"></span></span>
<input asp-for="@Model.password" type="password" class="form-control" name="password" placeholder="Password">
</div>
<hr>
<button class="btn btn-lg btn-outline-primary" type="submit"><i class="fa fa-sign-in"></i> Login</button>
</form>
</div>
</div>
</div>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

View File

@ -1,48 +0,0 @@
@using pwt_0x01_ng.Areas.Admin.Controllers;
@model RegisterViewModel
@{
ViewData["Title"] = "Register";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<div class="container">
<div class="row">
<br>
<div class="row row-sm-offset-3">
<div class="form-group col-xs-12 col-sm-6">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<form class="signupForm" action="" enctype="multipart/form-data" method="post">
<span asp-validation-for="@Model.username" class="text-danger"></span>
<div class="input-group">
<span class="input-group-addon"><span class="fa fa-user"></span></span>
<input asp-for="@Model.username" type="text" class="form-control" name="username" placeholder="Username">
</div>
<br>
<span asp-validation-for="@Model.email" class="text-danger"></span>
<div class="input-group">
<span class="input-group-addon"><span class="fa fa-envelope"></span></span>
<input asp-for="@Model.email" type="text" class="form-control" name="email" placeholder="Email">
</div>
<hr>
<span asp-validation-for="@Model.password" class="text-danger"></span>
<div class="input-group">
<span class="input-group-addon"><span class="fa fa-key"></span></span>
<input asp-for="@Model.password" type="password" class="form-control" name="password" placeholder="Password">
</div>
<br>
<span asp-validation-for="@Model.repeated_password" class="text-danger"></span>
<div class="input-group">
<span class="input-group-addon"><span class="fa fa-key"></span></span>
<input asp-for="@Model.repeated_password" type="password" class="form-control" name="repeated_password" placeholder="Repeated password">
</div>
<hr>
<button class="btn btn-lg btn-outline-primary" type="submit"><i class="fa fa-sign-in"></i> Register</button>
</form>
</div>
</div>
</div>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

View File

@ -1,3 +0,0 @@
@using pwt_0x01_ng
@using pwt_0x01_ng.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -1,3 +0,0 @@
@{
Layout = "_Layout";
}

View File

@ -1,73 +1,48 @@
using System.Diagnostics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using pwt_0x01_ng.Models;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.Dbfake;
namespace pwt_0x01_ng.Controllers
{
public class HomeController : Controller
{
readonly DBContext dbctx;
readonly ILogger<HomeController> logger;
public HomeController(DBContext dbctx, ILogger<HomeController> logger){
this.dbctx = dbctx;
this.logger = logger;
}
public class HomeController : Controller
{
private IList<Carousel> carousels = Dbfake.Carousels;
public async Task <IActionResult> Index()
{
UltimateViewModel uvm = new UltimateViewModel();
uvm.Carousels = await dbctx.Carousel.ToListAsync();
uvm.Products = await dbctx.Product.ToListAsync();
return View(uvm);
}
public IActionResult Index()
{
CarouselViewModel carousel = new CarouselViewModel();
carousel.Carousels = carousels;
return View(carousel);
}
public IActionResult About()
{
ViewData["Message"] = "Best project ever";
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}
return View();
}
public IActionResult Contact()
{
ViewData["Message"] = "Where you can find us";
logger.LogInformation("yay - somebody looking for our contact info");
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
return View();
}
public IActionResult Privacy()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
}
[Route("/Home/HandleError/{code:int}")]
public IActionResult HandleError(int code)
{
ViewData["ErrorMessage"] = $"Error {code}";
switch(code) {
case 403:
return View("~/Views/Shared/403.cshtml");
case 404:
return View("~/Views/Shared/404.cshtml");
case 500:
return View("~/Views/Shared/500.cshtml");
default:
return View("~/Views/Shared/unhandled_err_code.cshtml");
}
}
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
}
}
}

View File

@ -1,39 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using pwt_0x01_ng.Models;
using pwt_0x01_ng.Models.Database;
namespace pwt_0x01_ng.Controllers
{
public class ProductsController : Controller
{
readonly DBContext dbctx;
public ProductsController(DBContext dbctx){
this.dbctx = dbctx;
}
public async Task<IActionResult> Detail(int id){
Product p = await dbctx.Product.Where(p_item => p_item.id == id).FirstOrDefaultAsync();
if (p == null) return NotFound();
IList<Similar> s = await dbctx.Similar.Where(p_item => p_item.prod_id == id).ToListAsync();
IList<Product> similar = new List<Product>();
if (s != null) {
foreach (var s_item in s) {
var prod = await dbctx.Product.Where(p_item => p_item.id == s_item.similar_prod_id).FirstOrDefaultAsync();
if (prod != null) {
similar.Add(prod);
}
}
}
if (similar.Count > 0) {
ViewData["similar"] = similar;
}
return View(p);
}
}
}

View File

@ -1,99 +0,0 @@
upstream pwt {
server 127.0.0.1:8001;
}
server {
return 301 https://pwt.dotya.ml$request_uri;
listen 80;
listen [::]:80;
server_name pwt.dotya.ml;
return 404;
add_header Referrer-Policy "no-referrer, origin-when-cross-origin";
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag none;
add_header X-Real-IP $remote_addr;
add_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header X-Forwarded-Proto $scheme;
}
server {
server_name pwt.dotya.ml;
access_log /var/log/nginx/pwt.dotya.ml.access.log;
error_log /var/log/nginx/pwt.dotya.ml.error.log;
expires $expires;
etag on;
brotli on;
brotli_static on;
brotli_types *;
if ($http_user_agent ~* SemrushBot|morfeus) {
return 302 your-script-kiddie-box;
}
error_page 302 @blackhole;
location @blackhole {
add_header MESSAGE "YOU ALL SUCK D*CK";
add_header Retry-after "your script dies";
return 200;
}
location / {
proxy_pass http://pwt;
}
location = /robots.txt {
allow all;
add_header Content-Type "text/plain; charset=utf-8";
add_header X-Robots-Tag "none";
return 200 "User-agent: *\nDisallow: /";
}
add_header Content-Security-Policy "default-src 'none'; manifest-src 'self'; font-src 'self' https: blob:; img-src 'self'; script-src 'self' https: 'sha256-BU6NaT/mFkOb6wlKw9aAUV4i5MFr/Z/IFLIYAVFkmxQ=' 'sha256-V1j096ud9m6h5KncKkiAplx22jz14i0avalMtHLMFPs=' 'sha256-ggCJb9MSbkFha0PX0DCP2JxSZ4Vyz95IZKhP9nHXES8='; style-src 'self' https:; object-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Feature-Policy "geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; fullscreen 'self'; payment 'none';";
add_header Referrer-Policy "no-referrer, strict-origin-when-cross-origin";
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag none;
add_header X-Real-IP $remote_addr;
add_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header X-Forwarded-Proto $scheme;
listen [::]:443 ssl http2;
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/pwt.dotya.ml/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pwt.dotya.ml/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($host = www.pwt.dotya.ml) {
return 301 https://pwt.dotya.ml$request_uri;
}
listen 80;
listen [::]:80;
server_name www.pwt.dotya.ml;
return 404;
add_header Referrer-Policy "no-referrer, origin-when-cross-origin, strict-origin-when-cross-origin";
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag none;
add_header X-Real-IP $remote_addr;
add_header X-Forwarded-For $remote_addr;
listen [::]:443 ssl http2;
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/pwt.dotya.ml/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pwt.dotya.ml/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

View File

@ -1,12 +0,0 @@
[Unit]
Description=pwt
After=nginx.service docker.service
[Service]
Restart=on-failure
ExecStart=/usr/bin/docker-compose -f /etc/pwt/pwt-0x01-ng/docker-compose.prod.yml up --remove-orphans --build --scale netcoreultimateapp-prod=2
ExecStop=/usr/bin/docker-compose -f /etc/pwt/pwt-0x01-ng/docker-compose.prod.yml stop
[Install]
WantedBy=multi-user.target

View File

@ -1,17 +1,17 @@
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS base
FROM mcr.microsoft.com/dotnet/core/sdk:2.1-alpine
COPY . /src
WORKDIR /src
COPY *.csproj ./
RUN dotnet --version && dotnet --info
RUN dotnet restore
RUN dotnet clean
RUN dotnet build -c Release
COPY . ./
RUN dotnet publish -c Release -o bin/out
FROM mcr.microsoft.com/dotnet/aspnet:2.1
FROM mcr.microsoft.com/dotnet/aspnet:3.1-alpine
# debug drone
RUN pwd
COPY --from=0 /src/bin/Release/netcoreapp2.1/publish/ App/
WORKDIR /App
COPY --from=base /src/bin/out/ .
RUN chown -R nobody:nobody ./
USER nobody
ENV ASPNETCORE_ENVIRONMENT Production
ENV ASPNETCORE_URLS http://*:8081
ENV ASPNETCORE_ENVIRONMENT=Release
ENTRYPOINT ["dotnet", "pwt-0x01-ng.dll"]

View File

@ -1,17 +1,13 @@
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine
ENV UID 1000
ENV GID 1000
ENV UNAME unpriv
RUN adduser -D -u ${UID} -g ${GID} -H ${UNAME} -h /src
FROM mcr.microsoft.com/dotnet/core/sdk:2.1-alpine
COPY . /src
WORKDIR /src
COPY *.csproj ./
RUN dotnet --version && dotnet --info
RUN dotnet restore
RUN dotnet clean
COPY . ./
RUN dotnet build -c Debug -o bin/out
RUN chown -R "${UID}":"${GID}" ./ /root/
USER ${UNAME}
RUN dotnet build -c Debug
ENV ASPNETCORE_ENVIRONMENT=Development

View File

@ -1,32 +1,13 @@
dc = docker-compose
dccmd = COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose
dtag = netcoreultimateapp-prod
dtag = netcoreultimapp
dtagdev = netcoreultimapp-dev
dfile = Dockerfile
dfiledev = $(dfile).dev
lport = 8000
lportdev = 8001
CC = dotnet
dcmd = DOCKER_BUILDKIT=1 docker
pruneargs = system prune -af
dcmdrun = $(dcmd) run --rm
wdir = /src
kanikoimg = gcr.io/kaniko-project/executor@sha256:6ecc43ae139ad8cfa11604b592aaedddcabff8cef469eda303f1fb5afe5e3034
dargskaniko = -w=$(wdir) -v $$(pwd):$(wdir):z $(kanikoimg)
kanikoargs = -c=$(wdir) --use-new-run --snapshotMode=redo --no-push
krelease = $(dcmdrun) $(dargskaniko) -f=$(dfile) $(kanikoargs)
kdebug = $(dcmdrun) $(dargskaniko) -f=$(dfiledev) $(kanikoargs)
postkanikochown = sudo chown -R $$USER:$$USER ./
pgdbcapdrop = --cap-drop NET_ADMIN --cap-drop SYS_ADMIN
pgdbenv = -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=679968312e029a806c1905c40ec331aa199a1eb86bd0b9eb04057933e449bdc9ef8ef292a39b68cafa5689c901a17266 -e POSTGRES_INITDB_ARGS="--data-checksums"
pgdbname = pgdb
pgdbports = -p 127.0.0.1:5433:5432
pgdbvol = -v pgdbdata:/var/lib/postgresql/data
pgdbargs = run -d $(pgdbcapdrop) $(pgdbenv) --name $(pgdbname) $(pgdbports) $(pgdbvol) --restart unless-stopped
pgdbimg = postgres:13.1-alpine
zenv = DB_CONNECTION_STRING=$$(cat appsettings.Development.json | jq .db.Postgres | sed -e 's/5432/5433/' -e 's/=db/=localhost/' -e 's/"//g')
.PHONY: dev dockerbuild dockerdevbuild dockerrun dockerdevrun dockertest dockerdev kaniko clean prune pgdba pgdbz test dcdevb dcprodbuild dcdevup dcprodup
krelease = docker run --rm -it -w=$(wdir) -v $$PWD:$(wdir) gcr.io/kaniko-project/executor -f=$(dfile) -c=$(wdir) --use-new-run --snapshotMode=redo --no-push
kdebug = docker run --rm -it -w=$(wdir) -v $$PWD:$(wdir) gcr.io/kaniko-project/executor -f=$(dfiledev) -c=$(wdir) --use-new-run --snapshotMode=redo --no-push
dev: restore build run
@ -37,70 +18,42 @@ build:
$(CC) build .
run:
$(zenv) $(CC) watch run .
$(CC) run .
releasebuild: restore clean
$(CC) publish -c Release
dockerbuild:
$(dcmd) build \
@docker build \
--build-arg VCS_REF=`git rev-parse --short HEAD` \
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
-t $(dtag) -f $(dfile) --no-cache .
-t $(dtag) -f $(dfile) .
dockerdevbuild:
$(dcmd) build \
@docker build \
--build-arg VCS_REF=`git rev-parse --short HEAD` \
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
-t $(dtagdev) -f $(dfiledev) --no-cache .
-t $(dtagdev) -f $(dfiledev) .
dockerrun:
@echo ======================
@echo local port: $(lport)
@echo ======================
$(dcmdrun) -p $(lport):80 $(dtag)
docker run --rm -p $(lport):80 $(dtag)
dockerdevrun:
@echo ======================
@echo local dev port: $(lportdev)
@echo ======================
$(dcmdrun) -p $(lportdev):5000 $(dtagdev)
dcdevb:
$(dccmd) -f $(dc).yml build --no-cache --pull --progress tty
dcprodbuild:
$(dccmd) -f $(dc).prod.yml build --no-cache --pull --progress tty
dcdevup:
@echo ======================
@echo local dev port: $(lportdev)
@echo ======================
$(dccmd) -f $(dc).yml up --remove-orphans
dcprodup:
$(dccmd) -f $(dc).prod.yml up --remove-orphans --scale netcoreultimateapp-prod=2
docker run --rm -p $(lportdev):5000 $(dtagdev)
kaniko:
$(krelease)
$(postkanikochown)
$(kdebug)
$(postkanikochown)
dockerdev: dockerdevbuild dockerdevrun
dockertest: dockerdevbuild dockerbuild
test: releasebuild build dockertest kaniko
clean:
$(CC) clean
prune:
$(dcmd) $(pruneargs)
pgdba:
$(dcmd) $(pgdbargs) $(pgdbimg)
pgdbz:
$(dcmd) stop $(pgdbname)

View File

@ -1,17 +0,0 @@
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using pwt_0x01_ng.Models.Identity;
namespace pwt_0x01_ng.Models.ApplicationServices
{
public interface ISecurityApplicationService
{
Task<string[]> register(RegisterViewModel rvm, Roles role);
Task<bool> login(LoginViewModel lvm);
Task logout();
Task<User> find_user_by_username(string username);
Task<IList<string>> gimme_user_roles(User usr);
Task<User> gimme_current_user(ClaimsPrincipal claims);
}
}

View File

@ -1,66 +0,0 @@
using System.Linq;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using pwt_0x01_ng.Models.Identity;
namespace pwt_0x01_ng.Models.ApplicationServices
{
public class SecurityIdentityApplicationService : ISecurityApplicationService
{
UserManager<User> um;
SignInManager<User> sim;
public SecurityIdentityApplicationService(UserManager<User> um, SignInManager<User> sim){
this.um = um;
this.sim = sim;
}
public async Task<string[]> register(RegisterViewModel rvm, Roles role){
User usr = new User(){username = rvm.username, UserName = rvm.username, Name = rvm.username, LastName = "", password = rvm.password, Email = rvm.email, EmailConfirmed = true};
string[] errors = null;
var res = await um.CreateAsync(usr, rvm.password);
if(res.Succeeded){
var roleres = await um.AddToRoleAsync(usr, role.ToString());
if(!roleres.Succeeded){
int c = 0;
foreach (var err in res.Errors)
{
res.Errors.Append(res.Errors.ElementAt(c));
c++;
}
}
}
if(res.Errors != null && res.Errors.Count() > 0){
errors = new string[res.Errors.Count()];
int c = 0;
foreach (var err in res.Errors)
{
errors[c] = res.Errors.ElementAt(c).Description;
}
c++;
}
return errors;
}
public async Task<bool> login(LoginViewModel lvm){
var result = await sim.PasswordSignInAsync(lvm.username, lvm.password, config.remember_me_feature, config.lockout_on_failure);
return result.Succeeded;
}
public Task logout(){
return sim.SignOutAsync();
}
public Task<User> find_user_by_username(string username){
return um.FindByNameAsync(username);
}
public Task<IList<string>> gimme_user_roles(User usr){
return um.GetRolesAsync(usr);
}
public Task<User> gimme_current_user(ClaimsPrincipal claims){
return um.GetUserAsync(claims);
}
}
}

View File

@ -1,24 +1,14 @@
using Microsoft.AspNetCore.Http;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using pwt_0x01_ng.Models.Validation;
namespace pwt_0x01_ng.Models
{
[Table("Carousel")]
public class Carousel : Entity
{
[Required]
public string DataTarget { get; set; }
[NotMapped]
[FileTypeAttr("image")]
public IFormFile Image { get; set; }
[StringLength(255)]
public string ImageSrc { get; set; }
[Required]
[StringLength(50, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 1)]
public string ImageAlt { get; set; }
[Required]
public string CarouselContent { get; set; }
}
public class Carousel
{
public int id { get; set; }
public string DataTarget { get; set; }
public IFormFile Image { get; set; }
public string ImageSrc { get; set; }
public string ImageAlt { get; set; }
public string CarouselContent { get; set; }
}
}

View File

@ -2,8 +2,8 @@ using System.Collections.Generic;
namespace pwt_0x01_ng.Models
{
public class CarouselViewModel
{
public IList<Carousel> Carousels { get; set; }
}
public class CarouselViewModel
{
public IList<Carousel> Carousels { get; set; }
}
}

View File

@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace pwt_0x01_ng.Models
{
public class CustomerOrderViewModel
{
IList<Order> Orders { get; set; }
}
}

View File

@ -1,19 +0,0 @@
using System.Collections.Generic;
namespace pwt_0x01_ng.Models.Database
{
public static class CarouselHelper
{
public static IList<Carousel> GenerateCarousel()
{
IList<Carousel> carousels = new List<Carousel>()
{
new Carousel() { DataTarget = "#myCarousel", ImageSrc = "/images/banner1.svg", ImageAlt = "ASP.NET", CarouselContent = "Learn how to build ASP.NET apps that can run anywhere.<a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkID=525028&clcid=0x409\">Learn More</a>"},
new Carousel() { DataTarget = "#myCarousel", ImageSrc = "/images/banner2.svg", ImageAlt = "ASP.NET", CarouselContent = "There are powerful new features in Visual Studio for building modern web apps.<a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkID=525030&clcid=0x409\">Learn More</a>"},
new Carousel() { DataTarget = "#myCarousel", ImageSrc = "/images/banner3.svg", ImageAlt = "ASP.NET", CarouselContent = "Learn how Microsoft's Azure cloud platform allows you to build, deploy, and scale web apps.<a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkID=525027&clcid=0x409\">Learn More</a>"},
new Carousel() { DataTarget = "#myCarousel", ImageSrc = "/images/ms_loves_linux.jpeg", ImageAlt = "msloveslinux", CarouselContent = "ms loves linux"}
};
return carousels;
}
}
}

View File

@ -1,14 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace pwt_0x01_ng.Models.Database.Conf
{
public class CarouselConf : IEntityTypeConfiguration<Carousel>
{
public void Configure(EntityTypeBuilder<Carousel> builder)
{
builder.Property(nameof(Carousel.Created)).ValueGeneratedOnAdd().HasDefaultValueSql("NOW()");
builder.Property(nameof(Carousel.Updated)).ValueGeneratedOnAddOrUpdate().HasDefaultValueSql("NOW()");
}
}
}

View File

@ -1,15 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace pwt_0x01_ng.Models.Database.Conf
{
public class OrderConf : IEntityTypeConfiguration<Order>
{
public void Configure(EntityTypeBuilder<Order> builder)
{
builder.HasMany(order => order.OrderItems).WithOne(item => item.Order).IsRequired().HasForeignKey(item => item.Order_id).OnDelete(DeleteBehavior.Restrict);
builder.Property(nameof(Order.Created)).ValueGeneratedOnAdd().HasDefaultValueSql("NOW()");
builder.Property(nameof(Order.Updated)).ValueGeneratedOnAddOrUpdate().HasDefaultValueSql("NOW()");
}
}
}

View File

@ -1,14 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace pwt_0x01_ng.Models.Database.Conf
{
public class OrderItemConf : IEntityTypeConfiguration<OrderItem>
{
public void Configure(EntityTypeBuilder<OrderItem> builder)
{
builder.Property(nameof(OrderItem.Created)).ValueGeneratedOnAdd().HasDefaultValueSql("NOW()");
builder.Property(nameof(OrderItem.Updated)).ValueGeneratedOnAddOrUpdate().HasDefaultValueSql("NOW()");
}
}
}

View File

@ -1,14 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace pwt_0x01_ng.Models.Database.Conf
{
public class ProductConf : IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.Property(nameof(Product.Created)).ValueGeneratedOnAdd().HasDefaultValueSql("NOW()");
builder.Property(nameof(Product.Updated)).ValueGeneratedOnAddOrUpdate().HasDefaultValueSql("NOW()");
}
}
}

View File

@ -1,40 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using pwt_0x01_ng.Models.Identity;
using pwt_0x01_ng.Models.Database.Conf;
namespace pwt_0x01_ng.Models.Database
{
public class DBContext : IdentityDbContext<User, Role, int>
{
public DBContext(DbContextOptions<DBContext> options) : base(options)
{
}
public DbSet<Carousel> Carousel { get; set; }
public DbSet<Product> Product { get; set; }
public DbSet<Order> Order { get; set; }
public DbSet<OrderItem> OrderItem { get; set; }
public DbSet<Similar> Similar { get; set; }
protected override void OnModelCreating(ModelBuilder model_builder)
{
base.OnModelCreating(model_builder);
this.ApplyConfiguration(model_builder);
foreach(var entity_type in model_builder.Model.GetEntityTypes()){
entity_type.SetTableName(entity_type.GetTableName().Replace("AspNet", string.Empty));
}
}
protected virtual void ApplyConfiguration(ModelBuilder model_builder)
{
model_builder.ApplyConfiguration(new CarouselConf());
model_builder.ApplyConfiguration(new ProductConf());
model_builder.ApplyConfiguration(new OrderConf());
model_builder.ApplyConfiguration(new OrderItemConf());
}
}
}

View File

@ -1,121 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Identity;
using pwt_0x01_ng.Models.Identity;
namespace pwt_0x01_ng.Models.Database
{
public static class DBInit
{
public static void Init(DBContext dbContext)
{
dbContext.Database.EnsureCreated();
if(dbContext.Carousel.Count() == 0){
IList<Carousel> carousels = CarouselHelper.GenerateCarousel();
foreach (var c in carousels)
{
dbContext.Carousel.Add(c);
}
dbContext.SaveChanges();
}
if(dbContext.Product.Count() == 0){
IList<Product> products = ProductHelper.GenerateProduct();
foreach (var p in products)
{
dbContext.Product.Add(p);
}
dbContext.SaveChanges();
}
}
public static async Task EnsureRolesCreated(IServiceProvider sp){
using (var services = sp.CreateScope()){
RoleManager<Role> role_manager = services.ServiceProvider.GetRequiredService<RoleManager<Role>>();
string[] rolespls = Enum.GetNames(typeof(Roles));
foreach (var role in rolespls){
Console.WriteLine(role + " => " + role.GetType());
await role_manager.CreateAsync(new Role(role));
}
}
}
public static async Task EnsureManagerCreated(IServiceProvider sp){
using (var services = sp.CreateScope()){
UserManager<User> usr_manager = services.ServiceProvider.GetRequiredService<UserManager<User>>();
User manager = new User(){
UserName = "manager",
Email = "manager@manager.com",
Name = "manager",
LastName = "",
EmailConfirmed = true
};
var super_secure_password = "123"; /* TODO - rm this */
User manager_in_db = await usr_manager.FindByNameAsync(manager.UserName);
if (manager_in_db == null){
IdentityResult ir = new IdentityResult();
try {
ir = await usr_manager.CreateAsync(manager, super_secure_password);
} catch (Exception e){
Debug.WriteLine(e);
}
if(ir.Succeeded){
string[] rolespls = Enum.GetNames(typeof(Roles));
foreach (var role in rolespls){
if(role != Roles.Admin.ToString()){
await usr_manager.AddToRoleAsync(manager, role);
}
}
} else if (ir.Errors != null && ir.Errors.Count() >0){
foreach (var err in ir.Errors){
Debug.WriteLine("Error during manager role creation" + err.Code + " => " + err.Description);
}
}
}
}
}
public static async Task EnsureAdminCreated(IServiceProvider sp){
using (var services = sp.CreateScope()){
UserManager<User> usr_manager = services.ServiceProvider.GetRequiredService<UserManager<User>>();
User admin = new User(){
UserName = "admin",
Email = "admin@admin.com",
Name = "admin",
LastName = "",
EmailConfirmed = true
};
var super_secure_password = "123"; /* TODO - rm this */
User admin_in_db = await usr_manager.FindByNameAsync(admin.UserName);
if (admin_in_db == null){
IdentityResult ir = new IdentityResult();
try {
ir = await usr_manager.CreateAsync(admin, super_secure_password);
} catch (Exception e){
Debug.WriteLine(e);
}
if(ir.Succeeded){
string[] rolespls = Enum.GetNames(typeof(Roles));
foreach (var role in rolespls){
await usr_manager.AddToRoleAsync(admin, role);
}
} else if (ir.Errors != null && ir.Errors.Count() >0){
foreach (var err in ir.Errors){
Debug.WriteLine("Error during admin role creation" + err.Code + " => " + err.Description);
}
}
}
}
}
}
}

View File

@ -1,19 +0,0 @@
using System.Collections.Generic;
namespace pwt_0x01_ng.Models.Database
{
public static class ProductHelper
{
public static IList<Product> GenerateProduct()
{
IList<Product> products = new List<Product>()
{
new Product() { Name="a", Price=0, Description="aaaa", ImageSrc = "/images/banner1.svg", ImageAlt = "ASP.NET", Similar = {}},
new Product() { Name="b", Price=1, Description="bbbb", ImageSrc = "/images/banner2.svg", ImageAlt = "ASP.NET", Similar = {}},
new Product() { Name="c", Price=2, Description="cccc", ImageSrc = "/images/banner3.svg", ImageAlt = "ASP.NET", Similar = {}},
new Product() { Name="d", Price=3, Description="dddd", ImageSrc = "/images/ms_loves_linux.jpeg", ImageAlt = "msloveslinux", Similar = {}}
};
return products;
}
}
}

View File

@ -0,0 +1,20 @@
using System.Collections.Generic;
using Microsoft.IdentityModel.Tokens;
namespace pwt_0x01_ng.Models.Dbfake
{
public static class CarouselHelper
{
public static IList<Carousel> GenerateCarousel()
{
IList<Carousel> carousels = new List<Carousel>()
{
new Carousel() { id = 0, DataTarget = "#myCarousel", ImageSrc = "/images/banner1.svg", ImageAlt = "ASP.NET", CarouselContent = "Learn how to build ASP.NET apps that can run anywhere.<a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkID=525028&clcid=0x409\">Learn More</a>"},
new Carousel() { id = 1, DataTarget = "#myCarousel", ImageSrc = "/images/banner2.svg", ImageAlt = "ASP.NET", CarouselContent = "There are powerful new features in Visual Studio for building modern web apps.<a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkID=525030&clcid=0x409\">Learn More</a>"},
new Carousel() { id = 2, DataTarget = "#myCarousel", ImageSrc = "/images/banner3.svg", ImageAlt = "ASP.NET", CarouselContent = "Learn how Microsoft's Azure cloud platform allows you to build, deploy, and scale web apps.<a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkID=525027&clcid=0x409\">Learn More</a>"},
new Carousel() { id = 3, DataTarget = "#myCarousel", ImageSrc = "/images/ms_loves_linux.jpeg", ImageAlt = "msloveslinux", CarouselContent = "ms loves linux"}
};
return carousels;
}
}
}

15
Models/Dbfake/Dbfake.cs Normal file
View File

@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace pwt_0x01_ng.Models.Dbfake
{
public static class Dbfake
{
/* singe db table simulation*/
public static IList<Carousel> Carousels { get; set; }
static Dbfake()
{
Carousels = CarouselHelper.GenerateCarousel();
}
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace pwt_0x01_ng.Models
{
public abstract class Entity
{
[Key]
[Required]
public int id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime Created { get; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime Updated { get; }
}
}

View File

@ -1,9 +1,11 @@
using System;
namespace pwt_0x01_ng.Models
{
public class ErrorViewModel
{
public string RequestId { get; set; }
public class ErrorViewModel
{
public string RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}

View File

@ -1,9 +0,0 @@
using Microsoft.AspNetCore.Identity;
namespace pwt_0x01_ng.Models.Identity
{
public class Role : IdentityRole<int>
{
public Role(string name) : base(name){}
}
}

View File

@ -1,10 +0,0 @@
namespace pwt_0x01_ng.Models.Identity
{
public enum Roles
{
Admin,
Manager,
Customer
}
}

View File

@ -1,12 +0,0 @@
using Microsoft.AspNetCore.Identity;
namespace pwt_0x01_ng.Models.Identity
{
public class User : IdentityUser<int>
{
public virtual string username {get;set;}
public virtual string password {get;set;}
public virtual string Name {get; set;}
public virtual string LastName {get; set;}
}
}

View File

@ -1,15 +0,0 @@
using System.ComponentModel.DataAnnotations;
using pwt_0x01_ng.Models.Validation;
namespace pwt_0x01_ng.Models
{
public class LoginViewModel
{
[Required]
public string username {get; set;}
[Required]
[UniqueCharsAttr]
public string password {get; set;}
public bool login_failed {get; set;}
}
}

View File

@ -1,40 +1,38 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace pwt_0x01_ng.Models
{
public class MegaUpload
{
string webroot_path;
string folder_name;
string file_type;
public class MegaUpload
{
IHostingEnvironment hosting_env;
public MegaUpload(string webroot_path, string folder_name, string file_type){
this.webroot_path = webroot_path;
this.folder_name = folder_name;
this.file_type = file_type;
}
public async Task<string> DoMegaUpload(IFormFile iformfile)
{
string return_file_path = String.Empty;
var img = iformfile;
if(img != null && img.ContentType.ToLower().Contains(file_type) && img.Length > 0 && img.Length < 2000000){
var fname = Path.GetFileNameWithoutExtension(img.FileName);
var fext = Path.GetExtension(img.FileName);
/* in case such file already exists - wip */
/* var fname_rand = Path.GetRandomFileName()+Path.GetFileNameWithoutExtension(img.FileName); */
var f_relative = Path.Combine("images",folder_name, fname + fext);
var file_path = Path.Combine(webroot_path, f_relative);
public MegaUpload(IHostingEnvironment hosting_env){
this.hosting_env = hosting_env;
}
public async Task<bool> DoMegaUpload(Carousel carousel)
{
bool great_success = false;
var img = carousel.Image;
if(img != null && img.ContentType.ToLower().Contains("image") && img.Length > 0 && img.Length < 2000000){
var fname = Path.GetFileNameWithoutExtension(img.FileName);
var fext = Path.GetExtension(img.FileName);
/* in case such file already exists - wip */
/* var fname_rand = Path.GetRandomFileName()+Path.GetFileNameWithoutExtension(img.FileName); */
var f_relative = Path.Combine("images","carousels", fname + fext);
var file_path = Path.Combine(hosting_env.WebRootPath, f_relative);
using (var stream = new FileStream(file_path, FileMode.Create)){
await img.CopyToAsync(stream);
}
return_file_path = $"/{f_relative}";
/* great_success = true; */
}
return return_file_path;
}
}
using (var stream = new FileStream(file_path, FileMode.Create)){
await img.CopyToAsync(stream);
}
carousel.ImageSrc = $"/{f_relative}";
great_success = true;
}
return great_success;
}
}
}

View File

@ -1,22 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using pwt_0x01_ng.Models.Identity;
namespace pwt_0x01_ng.Models
{
[Table(nameof(Order))]
public class Order : Entity
{
[Required]
public string Order_Number { get; set; }
public IList<OrderItem> OrderItems { get; set; }
[ForeignKey(nameof(Identity.User))]
[Required]
public int User_id { get; set; }
[NotMapped]
public User usr { get; set; }
[Required]
public decimal Price_total { get; set; }
}
}

View File

@ -1,22 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace pwt_0x01_ng.Models
{
[Table(nameof(OrderItem))]
public class OrderItem : Entity
{
[ForeignKey(nameof(Order))]
[Required]
public int Order_id { get; set; }
[ForeignKey(nameof(Product))]
[Required]
public int Product_id { get; set; }
[Required]
public int Amount { get; set; }
[Required]
public decimal Price { get; set; }
public Order Order { get; set; }
public Product Product {get; set; }
}
}

View File

@ -1,31 +0,0 @@
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using pwt_0x01_ng.Models.Validation;
namespace pwt_0x01_ng.Models
{
[Table("Product")]
public class Product : Entity
{
[Required]
public string Name { get; set; }
[Required]
public int Price { get; set; }
[Required]
public string Description { get; set; }
[FileTypeAttr("image")]
[NotMapped]
public IFormFile Image { get; set; }
[StringLength(255)]
public string ImageSrc { get; set; }
[Required]
[StringLength(50, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 1)]
public string ImageAlt { get; set; }
[NotMapped]
public IList<SimilarProduct> Similar { get; set; }
[NotMapped]
public bool Selected { get; set; }
}
}

View File

@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace pwt_0x01_ng.Models
{
public class ProductViewModel
{
public IList<Product> Products { get; set; }
}
}

View File

@ -1,20 +0,0 @@
using System.ComponentModel.DataAnnotations;
using pwt_0x01_ng.Models.Validation;
namespace pwt_0x01_ng.Models
{
public class RegisterViewModel
{
[Required]
public string username {get; set;}
[Required]
[UniqueCharsAttr]
[RegularExpression(@"^.{2,}$", ErrorMessage = "Minimum password length is 2 characters.")]
public string password {get; set;}
[Required]
[Compare(nameof(password), ErrorMessage = "Passwords don't match.")]
public string repeated_password {get; set;}
[Required]
public string email {get; set;}
}
}

View File

@ -1,20 +0,0 @@
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
public static class SessionExtensions
{
public static T GetObject<T>(this ISession session, string key)
{
var data = session.GetString(key);
if (data == null)
{
return default(T);
}
return JsonConvert.DeserializeObject<T>(data);
}
public static void SetObject(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
}

View File

@ -1,18 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace pwt_0x01_ng.Models
{
[Table(nameof(Similar))]
public class Similar
{
[Required]
[Key]
public int id { get; set; }
[Required]
public int prod_id { get; set; }
[ForeignKey(nameof(Product))]
[Required]
public int similar_prod_id { get; set; }
}
}

View File

@ -1,8 +0,0 @@
namespace pwt_0x01_ng.Models
{
public class SimilarProduct
{
public int id { get; set; }
public bool Selected { get; set; }
}
}

View File

@ -1,9 +0,0 @@
using System.Collections.Generic;
namespace pwt_0x01_ng.Models
{
public class SimilarViewModel
{
public IList<Similar> Similar { get; set; }
}
}

View File

@ -1,10 +0,0 @@
using System.Collections.Generic;
namespace pwt_0x01_ng.Models
{
public class UltimateViewModel
{
public IList<Carousel> Carousels { get; set; }
public IList<Product> Products { get; set; }
}
}

View File

@ -1,48 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace pwt_0x01_ng.Models.Validation
{
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false)]
public class FileTypeAttr : ValidationAttribute, IClientModelValidator
{
private readonly string type;
public FileTypeAttr(string type){
this.type = type.ToLower();
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
if (value == null) {
/* img is optional as of now */
return ValidationResult.Success;
} else if (value is IFormFile iff) {
if(iff.ContentType.ToLower().Contains(type)) {
return ValidationResult.Success;
} else {
return new ValidationResult(GetErrorMessage(validationContext.MemberName), new List<string> { validationContext.MemberName });
}
}
throw new NotImplementedException($"Attribute {nameof(FileTypeAttr)} not implemented for object {value.GetType()}.");
}
protected string GetErrorMessage(string member_name) => $"make sure the {member_name} you picked really is of type <code>{type}/*</code>. <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types\" title=\"help\" target=\"_blank\" rel=\"noopener noreferer\"><em>help</em></a>";
public void AddValidation(ClientModelValidationContext ctx){
MergeAttribute(ctx.Attributes, "data-val", "true");
MergeAttribute(ctx.Attributes, "data-val-content", GetErrorMessage("file"));
MergeAttribute(ctx.Attributes, "data-val-content-type", type);
}
private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value){
if (attributes.ContainsKey(key)){
return false;
}
attributes.Add(key, value);
return true;
}
}
}

View File

@ -1,45 +0,0 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace pwt_0x01_ng.Models.Validation
{
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false)]
public class UniqueCharsAttr : ValidationAttribute, IClientModelValidator
{
public UniqueCharsAttr(){
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
if(value == null){return new ValidationResult(GetErrorMessage(), new List<string> { validationContext.MemberName });}
if (value is string phrase) {
int count = phrase.Distinct().Count();
if(count >= config.min_passwd_unique_chars) {
return ValidationResult.Success;
} else {
return new ValidationResult(GetErrorMessage(count, validationContext.MemberName), new List<string> { validationContext.MemberName });
}
}
throw new NotImplementedException($"Attribute {nameof(UniqueCharsAttr)} not implemented for object {value.GetType()}.");
}
protected string GetErrorMessage(int chars, string member_name) => $"not enough unique characters - provided: {chars}, wanted: {config.min_passwd_unique_chars}, problematic field: {member_name}";
protected string GetErrorMessage() => $"not enough unique characters. wanted: {config.min_passwd_unique_chars}";
public void AddValidation(ClientModelValidationContext ctx){
MergeAttribute(ctx.Attributes, "data-val", "true");
MergeAttribute(ctx.Attributes, "data-val-uniquechars", GetErrorMessage());
}
private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value){
if (attributes.ContainsKey(key)){
return false;
}
attributes.Add(key, value);
return true;
}
}
}

View File

@ -1,39 +1,24 @@
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using pwt_0x01_ng.Models.Database;
namespace pwt_0x01_ng
{
public class Program
{
public static async Task Main(string[] args)
{
IWebHost webHost = CreateWebHostBuilder(args).Build();
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
using (var scope = webHost.Services.CreateScope())
{
var serviceProvider = scope.ServiceProvider;
var dbctx = serviceProvider.GetRequiredService<DBContext>();
DBInit.Init(dbctx);
await DBInit.EnsureRolesCreated(serviceProvider);
await DBInit.EnsureAdminCreated(serviceProvider);
await DBInit.EnsureManagerCreated(serviceProvider);
}
webHost.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging((ctx, logging) => {
logging.ClearProviders();
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
});
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}

View File

@ -5,9 +5,7 @@
"launchBrowser": false,
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation",
"DB_CONNECTION_STRING": "User ID=postgres;Password=679968312e029a806c1905c40ec331aa199a1eb86bd0b9eb04057933e449bdc9ef8ef292a39b68cafa5689c901a17266;Server=localhost;Port=5433;Database=pwt;Integrated Security=true;Pooling=true;"
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}

View File

@ -3,23 +3,7 @@
this repo holds *sawce* for PWT .netcore mvc project 0x01-ng
### how to run this
- Makefile (you need `make` for this) --> see the [[Makefile]]
- direct `dotnet` (and/or `docker`) commands
#### useful Makefile targets
- `restore` --> runs `dotnet restore .`
- `clean` --> clean builds the project
- `build` --> builds the project
- `dockerdevbuild` --> clean-builds a container image from [[Dockerfile.dev]] (have a look in there for details)
- `dcdevb` --> compose clean build of a debug (dev) version, pulling db
- `dcdevup` --> runs the above (see [[docker-compose.yml]])
> you need to have created a db beforehand to run these
- `run` --> runs `$CURRENT_ENV dotnet watch run .`
- `dev` --> runs `restore build run` - this is kind of a convenience target
#### run using dotnet
> run the `dotnet` commands from the solution folder
> note that a preconfigured db is required for any kind of running the project (consider taking a look at [useful makefile targets](#useful-makefile-targets))
> run the following commands from the solution folder
on the first run, restore stuff
```sh

View File

@ -1,59 +0,0 @@
DROP TRIGGER IF EXISTS trigger_updated ON "Order";
CREATE OR REPLACE FUNCTION updatedattr() RETURNS trigger
AS $func$
BEGIN
NEW."Updated" := now();
NEW."Created" := OLD."Created";
RAISE NOTICE 'Order updated ''%'' on %', OLD."Order_Number", NEW."Updated";
RETURN NEW;
END;
$func$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_updated
BEFORE UPDATE ON "Order"
FOR EACH ROW
EXECUTE PROCEDURE updatedattr();
DROP TRIGGER IF EXISTS trigger_updated ON "Product";
CREATE OR REPLACE FUNCTION updatedattr() RETURNS trigger
AS $func$
BEGIN
NEW."Updated" := now();
NEW."Created" := OLD."Created";
RAISE NOTICE 'Product updated ''%'' on %', OLD."id", NEW."Updated";
RETURN NEW;
END;
$func$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_updated
BEFORE UPDATE ON "Product"
FOR EACH ROW
EXECUTE PROCEDURE updatedattr();
DROP TRIGGER IF EXISTS trigger_updated ON "OrderItem";
CREATE OR REPLACE FUNCTION updatedattr() RETURNS trigger
AS $func$
BEGIN
NEW."Updated" := now();
NEW."Created" := OLD."Created";
RAISE NOTICE 'OrderItem updated ''%'' on %', OLD."id", NEW."Updated";
RETURN NEW;
END;
$func$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_updated
BEFORE UPDATE ON "OrderItem"
FOR EACH ROW
EXECUTE PROCEDURE updatedattr();
DROP TRIGGER IF EXISTS trigger_updated ON "Carousel";
CREATE OR REPLACE FUNCTION updatedattr() RETURNS trigger
AS $func$
BEGIN
NEW."Updated" := now();
NEW."Created" := OLD."Created";
RAISE NOTICE 'Carousel updated ''%'' on %', OLD."id", NEW."Updated";
RETURN NEW;
END;
$func$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_updated
BEFORE UPDATE ON "Carousel"
FOR EACH ROW
EXECUTE PROCEDURE updatedattr();

View File

@ -1,133 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.CookiePolicy;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using pwt_0x01_ng.Models.Identity;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.ApplicationServices;
using Microsoft.EntityFrameworkCore;
namespace pwt_0x01_ng
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.Lax;
options.HttpOnly = HttpOnlyPolicy.Always;
options.Secure = CookieSecurePolicy.Always;
});
services.AddControllersWithViews();
IMvcBuilder builder = services.AddRazorPages();
#if DEBUG
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT").Equals("Development")){
builder.AddRazorRuntimeCompilation();
}
#endif
var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");
services.AddDbContext<DBContext>(options =>
options.UseNpgsql(
connectionString
)
);
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Lax;
options.HttpOnly = HttpOnlyPolicy.Always;
options.Secure = CookieSecurePolicy.Always;
});
services.AddIdentity<User, Role>().AddEntityFrameworkStores<DBContext>().AddDefaultTokenProviders();
services.Configure<IdentityOptions>(o =>
{
/* dev fun settings */
o.Password.RequireDigit = false;
o.Password.RequireUppercase = false;
o.Password.RequireLowercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = config.min_passwd_length;
o.Password.RequiredUniqueChars = 1;
o.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(1);
o.Lockout.MaxFailedAccessAttempts = 3;
o.Lockout.AllowedForNewUsers = false;
o.User.RequireUniqueEmail = true;
/* FIXME
* o.Password.RequireDigit = true;
* o.Password.RequiredLength = 18;
* o.Password.RequiredUniqueChars = 10;
* o.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
* o.Lockout.MaxFailedAccessAttempts = 3;
* o.Lockout.AllowedForNewUsers = true;
* o.User.RequireUniqueEmail = true;
*/
});
services.ConfigureApplicationCookie(o => {
o.Cookie.HttpOnly = true;
o.ExpireTimeSpan = TimeSpan.FromDays(2);
o.SlidingExpiration = true;
o.LoginPath = "/Security/Account/Login";
o.LogoutPath = "/Security/Account/Logout";
});
services.AddScoped<ISecurityApplicationService, SecurityIdentityApplicationService>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddResponseCompression();
services.AddSession();
}
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.EnvironmentName.Equals("Development"))
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStatusCodePages();
app.UseStatusCodePagesWithReExecute("/Home/HandleError/{0}");
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "areas",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Products}/{action=Details}/{id?}"
);
endpoints.MapHealthChecks("/health");
});
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseStaticFiles();
app.UseCookiePolicy();
}
}
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}

View File

@ -1,7 +1,7 @@
@{
ViewData["Title"] = "About";
ViewData["Title"] = "About";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>
<p>not much here now</p>
<p>Use this area to provide additional information.</p>

View File

@ -1,9 +1,17 @@
@{
ViewData["Title"] = "Contact";
ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"]</h2>
<h4>@ViewData["Message"]</h4>
<h3>@ViewData["Message"]</h3>
<address>
Earth &#x1F30D;
One Microsoft Way<br/>
Redmond, WA 98052-6399<br/>
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
<address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br/>
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

View File

@ -1,68 +1,107 @@
@model UltimateViewModel
@model CarouselViewModel
@{
ViewData["Title"] = "Home Page";
ViewData["Title"] = "Home Page";
}
@section Styles {
<environment include="Development">
<link rel="stylesheet" href="~/css/products.css"/>
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="~/css/products.css"/>
</environment>
<link rel="stylesheet" href="~/css/Stylezbro.css"/>
}
<div id="carouselpls">
<div class="row">
@{
if (Model != null && Model.Carousels.Count > 0)
{
<div id="@Model.Carousels[0].DataTarget.Substring(1, Model.Carousels[0].DataTarget.Length - 1)" class="carousel slide" data-ride="carousel" data-interval="6000">
<ol class="carousel-indicators">
@{
for (int i = 0; i < Model.Carousels.Count; i++)
{
string classli = String.Empty;
if (i == 0)
{
classli = "class=\"active\"";
}
<li data-target="@Model.Carousels[i].DataTarget" data-slide-to="@i" @Html.Raw(classli)></li>
}
}
</ol>
<div class="carousel-inner " role="listbox">
@{
for (int i = 0; i < Model.Carousels.Count; i++)
{
string classitem = "item";
if (i == 0)
{
classitem = "item active";
}
<div class="@classitem maxHeightCarousel">
<img src="@Model.Carousels[i].ImageSrc" alt="@Model.Carousels[i].ImageAlt" class="img-responsive"/>
<div class="carousel-caption" role="option">
<p>
@Html.Raw(Model.Carousels[i].CarouselContent)
</p>
</div>
</div>
}
}
</div>
<a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
}
}
</div>
</div>
<partial name="../Products/_partial_Products.cshtml"/>
@{
if (Model != null && Model.Carousels.Count > 0)
{
<div id="@Model.Carousels[0].DataTarget.Substring(1, Model.Carousels[0].DataTarget.Length - 1)" class="carousel slide" data-ride="carousel" data-interval="6000">
<ol class="carousel-indicators">
@{
for (int i = 0; i < Model.Carousels.Count; i++)
{
string classli = String.Empty;
if (i == 0)
{
classli = "class=\"active\"";
}
<li data-target="@Model.Carousels[i].DataTarget" data-slide-to="@i" @Html.Raw(classli)></li>
}
}
</ol>
<div class="carousel-inner " role="listbox">
@{
for (int i = 0; i < Model.Carousels.Count; i++)
{
string classitem = "item";
if (i == 0)
{
classitem = "item active";
}
<div class="@classitem maxHeightCarousel">
<img src="@Model.Carousels[i].ImageSrc" alt="@Model.Carousels[i].ImageAlt" class="img-responsive"/>
<div class="carousel-caption" role="option">
<p>
@Html.Raw(Model.Carousels[i].CarouselContent)
</p>
</div>
</div>
}
}
</div>
<a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<div class="row">
<div class="col-md-3">
<h2>Application uses</h2>
<ul>
<li>Sample pages using ASP.NET Core MVC</li>
<li>Theming using <a href="https://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a></li>
</ul>
</div>
<div class="col-md-3">
<h2>How to</h2>
<ul>
<li><a href="https://go.microsoft.com/fwlink/?LinkID=398600">Add a Controller and View</a></li>
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699315">Manage User Secrets using Secret Manager.</a></li>
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699316">Use logging to log a message.</a></li>
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699317">Add packages using NuGet.</a></li>
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699319">Target development, staging or production environment.</a></li>
</ul>
</div>
<div class="col-md-3">
<h2>Overview</h2>
<ul>
<li><a href="https://go.microsoft.com/fwlink/?LinkId=518008">Conceptual overview of what is ASP.NET Core</a></li>
<li><a href="https://go.microsoft.com/fwlink/?LinkId=699320">Fundamentals of ASP.NET Core such as Startup and middleware.</a></li>
<li><a href="https://go.microsoft.com/fwlink/?LinkId=398602">Working with Data</a></li>
<li><a href="https://go.microsoft.com/fwlink/?LinkId=398603">Security</a></li>
<li><a href="https://go.microsoft.com/fwlink/?LinkID=699321">Client side development</a>
</li>
<li>
<a href="https://go.microsoft.com/fwlink/?LinkID=699322">Develop on different platforms</a>
</li>
<li>
<a href="https://go.microsoft.com/fwlink/?LinkID=699323">Read more on the documentation site</a>
</li>
</ul>
</div>
<div class="col-md-3">
<h2>Run &amp; Deploy</h2>
<ul>
<li>
<a href="https://go.microsoft.com/fwlink/?LinkID=517851">Run your app</a>
</li>
<li>
<a href="https://go.microsoft.com/fwlink/?LinkID=517853">Run tools such as EF migrations and more</a>
</li>
<li>
<a href="https://go.microsoft.com/fwlink/?LinkID=398609">Publish to Microsoft Azure Web Apps</a>
</li>
</ul>
</div>
</div>
}
}

View File

@ -1,5 +1,5 @@
@{
ViewData["Title"] = "Privacy Policy";
ViewData["Title"] = "Privacy Policy";
}
<h2>@ViewData["Title"]</h2>

View File

@ -1,39 +0,0 @@
@model pwt_0x01_ng.Models.Product
@{
ViewData["Title"] = "Detail - " + @Model.Name;
}
<h2>Detail</h2>
<h3>@ViewData["Message"]</h3>
<div class="container">
<div class="row">
<div class="col-lg-3">
<h1 class="my-4">@Model.Name</h1>
<div class="list-group">
<a href="#" class="list-group-item active">Category 1</a>
<a href="#" class="list-group-item">Category 2</a>
<a href="#" class="list-group-item">Category 3</a>
</div>
</div><!-- /.col-lg-3 -->
<div class="col-lg-9">
<div class="card mt-4">
<img class="card-img-top img-fluid img-responsive" src="@Model.ImageSrc" alt="@Model.ImageAlt">
<div class="card-body">
<h3 class="card-title">@Model.Name</h3>
<h4>@Model.Price €</h4>
<p class="card-text">@Model.Description</p>
</div>
</div><!-- /.card -->
<div class="card card-outline-secondary my-4">
<div class="card-body">
<hr>
<input type="button" id="add_to_order" class="btn btn-primary" value="Add to order" onclick="Buy(@Model.id,'@Url.Action("AddOrderItemsToSession", "CustomerOrderNotCart", new { Area = "Customer" })', '#price_total', '@System.Globalization.CultureInfo.CurrentCulture.Name')" />
</div>
</div><!-- /.card -->
<partial name="_partial_SimilarProducts"/>
</div><!-- /.col-lg-9 -->
</div>
</div>

View File

@ -1,40 +0,0 @@
<!-- Page Content -->
<div class="container">
<div class="row">
<div class="col-lg-3">
<h1 class="my-4">Products</h1>
<div class="list-group">
<a href="#" class="list-group-item">Category 1</a>
<a href="#" class="list-group-item">Category 2</a>
<a href="#" class="list-group-item">Category 3</a>
</div>
</div><!-- /.col-lg-3 -->
<div class="col-lg-9">
<div class="row">
@{
if (Model != null && Model.Products.Count > 0){
for(int i = 0; i < Model.Products.Count; i++){
<div id="prod_card" class="col-lg-4 col-md-6 mb-4">
<div class="card h-100">
<a asp-area="" asp-controller="Products" asp-action="Detail" asp-route-id="@Model.Products[i].id"><img class="card-img-top img-responsive" id="prod_list_img" src="@Model.Products[i].ImageSrc" alt="@Model.Products[i].ImageAlt"></a>
<div class="card-body">
<h4 class="card-title">
<a asp-area="" asp-controller="Products" asp-action="Detail" asp-route-id="@Model.Products[i].id">@Model.Products[i].Name</a>
</h4>
<h5>@Model.Products[i].Price €</h5>
<p class="card-text">@Model.Products[i].Description</p>
</div>
<div class="card-footer">
<small class="text-muted">&#9733; &#9733; &#9733; &#9733; &#9733;</small>
</div>
</div>
</div>
}
} else {
<h3 class="text-info"><code>we apologise, no products are available at the moment.</code></h3>
}
}
</div><!-- /.row -->
</div><!-- /.col-lg-9 -->
</div><!-- /.row -->
</div><!-- /.container -->

View File

@ -1,35 +0,0 @@
@model pwt_0x01_ng.Models.Product
@{
IList<Product> similar;
similar = (IList<Product>) ViewData["similar"];
}
<div class="container">
<div class="col-lg-9">
<div class="row">
@if (similar != null && similar.Count > 0) {
<div class="col-lg-12 col-md-12">
<div class="col-lg-4 col-md-4">
<hr>
<label>Similar products</label>
</div>
</div>
int count_till = 3;
if (similar.Count < 3) count_till = similar.Count;
@for (int i = 0; i < count_till; i++) {
<div id="prod_card" class="col-lg-4 col-md-6 mb-4">
<div class="card h-100">
<a asp-area="" asp-controller="Products" asp-action="Detail" asp-route-id="@similar[i].id"><img class="card-img-top img-responsive" id="prod_list_img" src="@similar[i].ImageSrc" alt="@similar[i].ImageAlt"></a>
<div class="card-body">
<label><a asp-area="" asp-controller="Products" asp-action="Detail" asp-route-id="@similar[i].id">@similar[i].Name</a></label>
<div class="card-text">@similar[i].Description</div>
</div>
<div class="card-footer">
<div class="text-muted">@similar[i].Price €</div>
</div>
</div>
</div>
}
}
</div>
</div>
</div>

View File

@ -1,7 +0,0 @@
@{
ViewData["Title"] = "403 Forbidden";
}
<partial name="_errdivtop_part"/>
<h2 class="text-secondary">You are not authorized to access the resource.</h2>
<partial name="_errdivbottom_part"/>

Some files were not shown because too many files have changed in this diff Show More