mirror of
https://github.com/bitwarden/server.git
synced 2024-12-26 17:37:36 +01:00
organization search page
This commit is contained in:
parent
cd262e81c8
commit
7475ed7318
49
src/Admin/Controllers/OrganizationsController.cs
Normal file
49
src/Admin/Controllers/OrganizationsController.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Bit.Core.Repositories;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Bit.Admin.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Bit.Core.Models.Table;
|
||||||
|
|
||||||
|
namespace Bit.Admin.Controllers
|
||||||
|
{
|
||||||
|
[Authorize]
|
||||||
|
public class OrganizationsController : Controller
|
||||||
|
{
|
||||||
|
private readonly IOrganizationRepository _organizationRepository;
|
||||||
|
|
||||||
|
public OrganizationsController(IOrganizationRepository organizationRepository)
|
||||||
|
{
|
||||||
|
_organizationRepository = organizationRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IActionResult> Index(string name = null, string userEmail = null, bool paid = false,
|
||||||
|
int page = 1, int count = 25)
|
||||||
|
{
|
||||||
|
if(page < 1)
|
||||||
|
{
|
||||||
|
page = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count < 1)
|
||||||
|
{
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var skip = (page - 1) * count;
|
||||||
|
var organizations = await _organizationRepository.SearchAsync(name, userEmail, paid ? (bool?)true : null,
|
||||||
|
skip, count);
|
||||||
|
return View(new OrganizationsModel
|
||||||
|
{
|
||||||
|
Items = organizations as List<Organization>,
|
||||||
|
Name = string.IsNullOrWhiteSpace(name) ? null : name,
|
||||||
|
UserEmail = string.IsNullOrWhiteSpace(userEmail) ? null : userEmail,
|
||||||
|
Paid = paid,
|
||||||
|
Page = page,
|
||||||
|
Count = count
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -32,10 +32,10 @@ namespace Bit.Admin.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
var skip = (page - 1) * count;
|
var skip = (page - 1) * count;
|
||||||
var users = await _userRepository.SearchByEmailAsync(email, skip, count);
|
var users = await _userRepository.SearchAsync(email, skip, count);
|
||||||
return View(new UsersModel
|
return View(new UsersModel
|
||||||
{
|
{
|
||||||
Users = users as List<User>,
|
Items = users as List<User>,
|
||||||
Email = string.IsNullOrWhiteSpace(email) ? null : email,
|
Email = string.IsNullOrWhiteSpace(email) ? null : email,
|
||||||
Page = page,
|
Page = page,
|
||||||
Count = count
|
Count = count
|
||||||
|
11
src/Admin/Models/OrganizationsModel.cs
Normal file
11
src/Admin/Models/OrganizationsModel.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Bit.Core.Models.Table;
|
||||||
|
|
||||||
|
namespace Bit.Admin.Models
|
||||||
|
{
|
||||||
|
public class OrganizationsModel : PagedModel<Organization>
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string UserEmail { get; set; }
|
||||||
|
public bool Paid { get; set; }
|
||||||
|
}
|
||||||
|
}
|
13
src/Admin/Models/PagedModel.cs
Normal file
13
src/Admin/Models/PagedModel.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Bit.Admin.Models
|
||||||
|
{
|
||||||
|
public abstract class PagedModel<T>
|
||||||
|
{
|
||||||
|
public List<T> Items { get; set; }
|
||||||
|
public int Page { get; set; }
|
||||||
|
public int Count { get; set; }
|
||||||
|
public int? PreviousPage => Page < 2 ? (int?)null : Page - 1;
|
||||||
|
public int? NextPage => Items.Count < Count ? (int?)null : Page + 1;
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,9 @@
|
|||||||
using System.Collections;
|
using Bit.Core.Models.Table;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Bit.Core.Models.Table;
|
|
||||||
|
|
||||||
namespace Bit.Admin.Models
|
namespace Bit.Admin.Models
|
||||||
{
|
{
|
||||||
public class UsersModel
|
public class UsersModel : PagedModel<User>
|
||||||
{
|
{
|
||||||
public List<User> Users { get; set; }
|
|
||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
public int Page { get; set; }
|
|
||||||
public int Count { get; set; }
|
|
||||||
public int? PreviousPage => Page < 2 ? (int?)null : Page - 1;
|
|
||||||
public int? NextPage => Users.Count < Count ? (int?)null : Page + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
124
src/Admin/Views/Organizations/Index.cshtml
Normal file
124
src/Admin/Views/Organizations/Index.cshtml
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
@model OrganizationsModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Organizations";
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1>Organizations</h1>
|
||||||
|
|
||||||
|
<form class="form-inline mb-3" method="get">
|
||||||
|
<label class="sr-only" asp-for="Name">Name</label>
|
||||||
|
<input type="text" class="form-control mb-2 mr-2" placeholder="Name" asp-for="Name" name="name">
|
||||||
|
<label class="sr-only" asp-for="UserEmail">User email</label>
|
||||||
|
<input type="text" class="form-control mb-2 mr-2" placeholder="User email" asp-for="UserEmail" name="userEmail">
|
||||||
|
<div class="form-check mr-2 mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" asp-for="Paid" name="paid">
|
||||||
|
<label class="form-check-label" asp-for="Paid">Paid</label>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary mb-2" title="Search"><i class="fa fa-search"></i> Search</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th style="width: 190px;">Plan</th>
|
||||||
|
<th style="width: 80px;">Seats</th>
|
||||||
|
<th style="width: 150px;">Created</th>
|
||||||
|
<th style="width: 150px; min-width: 150px;">Details</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@if(!Model.Items.Any())
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td colspan="5">No results to list.</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@foreach(var org in Model.Items)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="#">@org.Name</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@org.Plan
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@org.Seats
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span title="@org.CreationDate.ToString()">
|
||||||
|
@org.CreationDate.ToShortDateString()
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if(!string.IsNullOrWhiteSpace(org.GatewaySubscriptionId))
|
||||||
|
{
|
||||||
|
<i class="fa fa-usd fa-lg fa-fw" title="Paid"></i>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<i class="fa fa-smile-o fa-lg fa-fw text-muted" title="Freeloader"></i>
|
||||||
|
}
|
||||||
|
@if(org.MaxStorageGb.HasValue && org.MaxStorageGb > 1)
|
||||||
|
{
|
||||||
|
<i class="fa fa-plus-square fa-lg fa-fw"
|
||||||
|
title="Additional Storage, @(org.MaxStorageGb - 1) GB"></i>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<i class="fa fa-plus-square-o fa-lg fa-fw text-muted"
|
||||||
|
title="No Additional Storage"></i>
|
||||||
|
}
|
||||||
|
@if(org.Enabled)
|
||||||
|
{
|
||||||
|
<i class="fa fa-check-circle fa-lg fa-fw"
|
||||||
|
title="Enabled, expires @(org.ExpirationDate?.ToShortDateString() ?? "-")"></i>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<i class="fa fa-times-circle-o fa-lg fa-fw text-muted" title="Disabled"></i>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<ul class="pagination">
|
||||||
|
@if(Model.PreviousPage.HasValue)
|
||||||
|
{
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" asp-action="Index" asp-route-page="@Model.PreviousPage.Value"
|
||||||
|
asp-route-count="@Model.Count" asp-route-userEmail="@Model.UserEmail"
|
||||||
|
asp-route-name="@Model.Name" asp-route-paid="@Model.Paid">Previous</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<li class="page-item disabled">
|
||||||
|
<a class="page-link" href="#" tabindex="-1">Previous</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
@if(Model.NextPage.HasValue)
|
||||||
|
{
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" asp-action="Index" asp-route-page="@Model.NextPage.Value"
|
||||||
|
asp-route-count="@Model.Count" asp-route-userEmail="@Model.UserEmail"
|
||||||
|
asp-route-name="@Model.Name" asp-route-paid="@Model.Paid">Next</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<li class="page-item disabled">
|
||||||
|
<a class="page-link" href="#" tabindex="-1">Next</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
@ -33,6 +33,9 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" asp-controller="Users">Users</a>
|
<a class="nav-link" asp-controller="Users">Users</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" asp-controller="Organizations">Organizations</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,12 +7,8 @@
|
|||||||
|
|
||||||
<form class="form-inline mb-3" method="get">
|
<form class="form-inline mb-3" method="get">
|
||||||
<label class="sr-only" asp-for="Email">Email</label>
|
<label class="sr-only" asp-for="Email">Email</label>
|
||||||
<div class="input-group">
|
<input type="text" class="form-control mb-2 mr-2" placeholder="Email" asp-for="Email" name="email">
|
||||||
<input type="text" class="form-control" placeholder="Email" asp-for="Email" name="email">
|
<button type="submit" class="btn btn-primary mb-2" title="Search"><i class="fa fa-search"></i> Search</button>
|
||||||
<div class="input-group-append">
|
|
||||||
<button type="submit" class="btn btn-primary" title="Search"><i class="fa fa-search"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@ -21,11 +17,11 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
<th style="width: 150px;">Created</th>
|
<th style="width: 150px;">Created</th>
|
||||||
<th style="width: 150px; min-width: 150px;">Details</th>
|
<th style="width: 170px; min-width: 150px;">Details</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@if(!Model.Users.Any())
|
@if(!Model.Items.Any())
|
||||||
{
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4">No results to list.</td>
|
<td colspan="4">No results to list.</td>
|
||||||
@ -33,7 +29,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@foreach(var user in Model.Users)
|
@foreach(var user in Model.Items)
|
||||||
{
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -48,19 +44,29 @@
|
|||||||
@if(user.Premium)
|
@if(user.Premium)
|
||||||
{
|
{
|
||||||
<i class="fa fa-star fa-lg fa-fw"
|
<i class="fa fa-star fa-lg fa-fw"
|
||||||
title="Premium, expires @(user.PremiumExpirationDate?.ToShortDateString() ?? "Never")"></i>
|
title="Premium, expires @(user.PremiumExpirationDate?.ToShortDateString() ?? "-")"></i>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<i class="fa fa-star-o fa-lg fa-fw text-muted" title="Not Premium"></i>
|
<i class="fa fa-star-o fa-lg fa-fw text-muted" title="Not Premium"></i>
|
||||||
}
|
}
|
||||||
|
@if(user.MaxStorageGb.HasValue && user.MaxStorageGb > 1)
|
||||||
|
{
|
||||||
|
<i class="fa fa-plus-square fa-lg fa-fw"
|
||||||
|
title="Additional Storage, @(user.MaxStorageGb - 1) GB"></i>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<i class="fa fa-plus-square-o fa-lg fa-fw text-muted"
|
||||||
|
title="No Additional Storage"></i>
|
||||||
|
}
|
||||||
@if(user.EmailVerified)
|
@if(user.EmailVerified)
|
||||||
{
|
{
|
||||||
<i class="fa fa-check-circle fa-lg fa-fw" title="Email Verified"></i>
|
<i class="fa fa-check-circle fa-lg fa-fw" title="Email Verified"></i>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<i class="fa fa-check-circle-o fa-lg fa-fw text-muted" title="Email Not Verified"></i>
|
<i class="fa fa-times-circle-o fa-lg fa-fw text-muted" title="Email Not Verified"></i>
|
||||||
}
|
}
|
||||||
@if(user.TwoFactorIsEnabled())
|
@if(user.TwoFactorIsEnabled())
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@ namespace Bit.Core.Repositories
|
|||||||
{
|
{
|
||||||
Task<ICollection<Organization>> GetManyByEnabledAsync();
|
Task<ICollection<Organization>> GetManyByEnabledAsync();
|
||||||
Task<ICollection<Organization>> GetManyByUserIdAsync(Guid userId);
|
Task<ICollection<Organization>> GetManyByUserIdAsync(Guid userId);
|
||||||
|
Task<ICollection<Organization>> SearchAsync(string name, string userEmail, bool? paid, int skip, int take);
|
||||||
Task UpdateStorageAsync(Guid id);
|
Task UpdateStorageAsync(Guid id);
|
||||||
Task<ICollection<OrganizationAbility>> GetManyAbilitiesAsync();
|
Task<ICollection<OrganizationAbility>> GetManyAbilitiesAsync();
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ namespace Bit.Core.Repositories
|
|||||||
public interface IUserRepository : IRepository<User, Guid>
|
public interface IUserRepository : IRepository<User, Guid>
|
||||||
{
|
{
|
||||||
Task<User> GetByEmailAsync(string email);
|
Task<User> GetByEmailAsync(string email);
|
||||||
Task<ICollection<User>> SearchByEmailAsync(string email, int skip, int take);
|
Task<ICollection<User>> SearchAsync(string email, int skip, int take);
|
||||||
Task<ICollection<User>> GetManyByPremiumAsync(bool premium);
|
Task<ICollection<User>> GetManyByPremiumAsync(bool premium);
|
||||||
Task<string> GetPublicKeyAsync(Guid id);
|
Task<string> GetPublicKeyAsync(Guid id);
|
||||||
Task<DateTime> GetAccountRevisionDateAsync(Guid id);
|
Task<DateTime> GetAccountRevisionDateAsync(Guid id);
|
||||||
|
@ -45,6 +45,20 @@ namespace Bit.Core.Repositories.SqlServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<ICollection<Organization>> SearchAsync(string name, string userEmail, bool? paid,
|
||||||
|
int skip, int take)
|
||||||
|
{
|
||||||
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
{
|
||||||
|
var results = await connection.QueryAsync<Organization>(
|
||||||
|
"[dbo].[Organization_Search]",
|
||||||
|
new { Name = name, UserEmail = userEmail, Paid = paid, Skip = skip, Take = take },
|
||||||
|
commandType: CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
return results.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task UpdateStorageAsync(Guid id)
|
public async Task UpdateStorageAsync(Guid id)
|
||||||
{
|
{
|
||||||
using(var connection = new SqlConnection(ConnectionString))
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
|
@ -37,12 +37,12 @@ namespace Bit.Core.Repositories.SqlServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ICollection<User>> SearchByEmailAsync(string email, int skip, int take)
|
public async Task<ICollection<User>> SearchAsync(string email, int skip, int take)
|
||||||
{
|
{
|
||||||
using(var connection = new SqlConnection(ConnectionString))
|
using(var connection = new SqlConnection(ConnectionString))
|
||||||
{
|
{
|
||||||
var results = await connection.QueryAsync<User>(
|
var results = await connection.QueryAsync<User>(
|
||||||
$"[{Schema}].[{Table}_SearchByEmail]",
|
$"[{Schema}].[{Table}_Search]",
|
||||||
new { Email = email, Skip = skip, Take = take },
|
new { Email = email, Skip = skip, Take = take },
|
||||||
commandType: CommandType.StoredProcedure);
|
commandType: CommandType.StoredProcedure);
|
||||||
|
|
||||||
|
@ -224,6 +224,7 @@
|
|||||||
<Build Include="dbo\Stored Procedures\Event_ReadPageByCipherId.sql" />
|
<Build Include="dbo\Stored Procedures\Event_ReadPageByCipherId.sql" />
|
||||||
<Build Include="dbo\Stored Procedures\Event_ReadPageByOrganizationIdActingUserId.sql" />
|
<Build Include="dbo\Stored Procedures\Event_ReadPageByOrganizationIdActingUserId.sql" />
|
||||||
<Build Include="dbo\Stored Procedures\Organization_ReadAbilities.sql" />
|
<Build Include="dbo\Stored Procedures\Organization_ReadAbilities.sql" />
|
||||||
<Build Include="dbo\Stored Procedures\User_SearchByEmail.sql" />
|
<Build Include="dbo\Stored Procedures\User_Search.sql" />
|
||||||
|
<Build Include="dbo\Stored Procedures\Organization_Search.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
34
src/Sql/dbo/Stored Procedures/Organization_Search.sql
Normal file
34
src/Sql/dbo/Stored Procedures/Organization_Search.sql
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
CREATE PROCEDURE [dbo].[Organization_Search]
|
||||||
|
@Name NVARCHAR(50),
|
||||||
|
@UserEmail NVARCHAR(50),
|
||||||
|
@Paid BIT,
|
||||||
|
@Skip INT = 0,
|
||||||
|
@Take INT = 25
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
DECLARE @NameLikeSearch NVARCHAR(55) = '%' + @Name + '%'
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
O.*
|
||||||
|
FROM
|
||||||
|
[dbo].[OrganizationView] O
|
||||||
|
INNER JOIN
|
||||||
|
[dbo].[OrganizationUser] OU ON O.[Id] = OU.[OrganizationId]
|
||||||
|
INNER JOIN
|
||||||
|
[dbo].[User] U ON U.[Id] = OU.[UserId]
|
||||||
|
WHERE
|
||||||
|
(@Name IS NULL OR O.[Name] LIKE @NameLikeSearch)
|
||||||
|
AND (@UserEmail IS NULL OR U.[Email] = @UserEmail)
|
||||||
|
AND
|
||||||
|
(
|
||||||
|
@Paid IS NULL OR
|
||||||
|
(
|
||||||
|
(@Paid = 1 AND O.[GatewaySubscriptionId] IS NOT NULL) OR
|
||||||
|
(@Paid = 0 AND O.[GatewaySubscriptionId] IS NULL)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ORDER BY O.[CreationDate] DESC
|
||||||
|
OFFSET @Skip ROWS
|
||||||
|
FETCH NEXT @Take ROWS ONLY
|
||||||
|
END
|
@ -1,4 +1,4 @@
|
|||||||
CREATE PROCEDURE [dbo].[User_SearchByEmail]
|
CREATE PROCEDURE [dbo].[User_Search]
|
||||||
@Email NVARCHAR(50),
|
@Email NVARCHAR(50),
|
||||||
@Skip INT = 0,
|
@Skip INT = 0,
|
||||||
@Take INT = 25
|
@Take INT = 25
|
@ -1,10 +1,10 @@
|
|||||||
IF OBJECT_ID('[dbo].[User_SearchByEmail]') IS NOT NULL
|
IF OBJECT_ID('[dbo].[User_Search]') IS NOT NULL
|
||||||
BEGIN
|
BEGIN
|
||||||
DROP PROCEDURE [dbo].[User_SearchByEmail]
|
DROP PROCEDURE [dbo].[User_Search]
|
||||||
END
|
END
|
||||||
GO
|
GO
|
||||||
|
|
||||||
CREATE PROCEDURE [dbo].[User_SearchByEmail]
|
CREATE PROCEDURE [dbo].[User_Search]
|
||||||
@Email NVARCHAR(50),
|
@Email NVARCHAR(50),
|
||||||
@Skip INT = 0,
|
@Skip INT = 0,
|
||||||
@Take INT = 25
|
@Take INT = 25
|
||||||
@ -24,3 +24,45 @@ BEGIN
|
|||||||
FETCH NEXT @Take ROWS ONLY
|
FETCH NEXT @Take ROWS ONLY
|
||||||
END
|
END
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_ID('[dbo].[Organization_Search]') IS NOT NULL
|
||||||
|
BEGIN
|
||||||
|
DROP PROCEDURE [dbo].[Organization_Search]
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE PROCEDURE [dbo].[Organization_Search]
|
||||||
|
@Name NVARCHAR(50),
|
||||||
|
@UserEmail NVARCHAR(50),
|
||||||
|
@Paid BIT,
|
||||||
|
@Skip INT = 0,
|
||||||
|
@Take INT = 25
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON
|
||||||
|
DECLARE @NameLikeSearch NVARCHAR(55) = '%' + @Name + '%'
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
O.*
|
||||||
|
FROM
|
||||||
|
[dbo].[OrganizationView] O
|
||||||
|
INNER JOIN
|
||||||
|
[dbo].[OrganizationUser] OU ON O.[Id] = OU.[OrganizationId]
|
||||||
|
INNER JOIN
|
||||||
|
[dbo].[User] U ON U.[Id] = OU.[UserId]
|
||||||
|
WHERE
|
||||||
|
(@Name IS NULL OR O.[Name] LIKE @NameLikeSearch)
|
||||||
|
AND (@UserEmail IS NULL OR U.[Email] = @UserEmail)
|
||||||
|
AND
|
||||||
|
(
|
||||||
|
@Paid IS NULL OR
|
||||||
|
(
|
||||||
|
(@Paid = 1 AND O.[GatewaySubscriptionId] IS NOT NULL) OR
|
||||||
|
(@Paid = 0 AND O.[GatewaySubscriptionId] IS NULL)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ORDER BY O.[CreationDate] DESC
|
||||||
|
OFFSET @Skip ROWS
|
||||||
|
FETCH NEXT @Take ROWS ONLY
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
Loading…
Reference in New Issue
Block a user