public IActionResult Count([FromQuery][QueryObject] QCEventQueryFilter filter,
                                   [FromQuery] QCEventQuerySort sort,
                                   [FromQuery] QCEventQueryPaging paging,
                                   [FromQuery] QCEventQueryOptions options)
        {
            var validationData = _service.ValidateCountQCEvents(
                User, filter, sort, paging, options);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var query = _service.GetQueryableQCEvent(options, filter, sort, paging);
            var count = query.Count();

            return(Ok(AppResult.Success(count)));
        }
        public IActionResult UpdateSeenStatus([FromQuery][QueryObject] QCEventQueryFilter filter,
                                              [FromQuery] QCEventQuerySort sort,
                                              [FromQuery] QCEventQueryPaging paging,
                                              [FromQuery] QCEventQueryOptions options)
        {
            var validationData = _service.ValidateUpdateSeenStatus(
                User, filter, sort, paging, options);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var query   = _service.GetQueryableQCEventForUpdate(options, filter, sort, paging);
            var updated = _service.UpdateEventsSeenStatus(query, true);

            return(Ok(AppResult.Success(updated)));
        }
        public IActionResult Update(int id, UpdateResourceModel model)
        {
            var entity = _service.Resources.Id(id).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var validationData = _service.ValidateUpdateResource(User, entity, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            _service.UpdateResource(entity, model);
            context.SaveChanges();
            return(NoContent());
        }
        public async Task <IActionResult> GetCalendar(
            [FromQuery][DefaultDateTimeModelBinder] DateTime date,
            [FromQuery] BookingQueryProjection projection,
            [FromQuery] BookingQueryOptions options)
        {
            var validationData = _service.ValidateGetOwnerBookings(
                User, date, projection, options);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var member = _memberService.Members.Id(UserId).FirstOrDefault();
            var result = await _service.QueryCalendarDynamic(User, member, projection,
                                                             date, validationData.TempData, options);

            return(Ok(AppResult.Success(data: result)));
        }
        public IActionResult Create(CreateResourceModel model)
        {
            var validationData = _service.ValidateCreateResource(User, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var entity = _service.CreateResource(model);

            context.SaveChanges();
            // must be in transaction
            var ev = _ev_service.CreateResource(entity, User);

            context.SaveChanges();
            return(Created($"/{Business.Constants.ApiEndpoint.RESOURCE_API}?id={entity.Id}",
                           AppResult.Success(entity.Id)));
        }
Exemple #6
0
        public async Task <IActionResult> CreateRole(CreateRoleModel model)
        {
            var validationData = _service.ValidateCreateRole(User, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var result = await _service.CreateRoleAsync(model);

            if (result.Succeeded)
            {
                return(Ok(AppResult.Success(result)));
            }
            foreach (var err in result.Errors)
            {
                ModelState.AddModelError(err.Code, err.Description);
            }
            return(BadRequest(AppResult.FailValidation(ModelState)));
        }
        public async Task <IActionResult> RemoveRole(RemoveRolesFromUserModel model)
        {
            var entity = await _service.GetUserByUserNameAsync(model.username);

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var result = await _service.RemoveUserFromRolesAsync(entity, model.roles);

            if (result.Succeeded)
            {
                return(NoContent());
            }
            foreach (var err in result.Errors)
            {
                ModelState.AddModelError(err.Code, err.Description);
            }
            return(BadRequest(AppResult.FailValidation(ModelState)));
        }
Exemple #8
0
        public IActionResult CreateDepartment(CreateDepartmentModel model)
        {
            var validationData = _service.ValidateCreateDepartment(User, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            using (var trans = context.Database.BeginTransaction())
            {
                var entity = _service.CreateDepartment(model);
                //log event
                var ev = _sysService.GetEventForCreateDepartment(
                    $"Admin {UserEmail} created a new department", User, entity);
                _sysService.CreateAppEvent(ev);
                //end log event
                context.SaveChanges();
                trans.Commit();
            }
            return(NoContent());
        }
        public IActionResult ChangeCurrentDeviceConfig(ChangeCurrentDeviceConfigModel model)
        {
            var entity = _service.DeviceConfigs.Id(model.ConfigId).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var validationData = _service.ValidateChangeCurrentDeviceConfig(User, entity, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var oldCurrent = _service.DeviceConfigs.IsCurrent().FirstOrDefault();

            _service.ChangeCurrentDeviceConfig(entity, oldCurrent);
            context.SaveChanges();
            Startup.SetCurrentConfig(entity);
            return(NoContent());
        }
        public IActionResult GetAllImages()
        {
            var validationData = _service.ValidateGetAllImages(User);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var tempPath = _fileService.GetLocalTempFilePath(ext: ".zip");

            try
            {
                _fileService.ZipFolderToDir(Settings.Instance.QCEventImageFolderPath, tempPath);
                return(PhysicalFile(tempPath, MediaTypeNames.Application.Zip, "images.zip"));
            }
            catch (Exception e)
            {
                _fileService.DeleteFile(tempPath, "");
                throw e;
            }
        }
        public async Task <IActionResult> Get([FromQuery][QueryObject] QCEventQueryFilter filter,
                                              [FromQuery] QCEventQuerySort sort,
                                              [FromQuery] QCEventQueryProjection projection,
                                              [FromQuery] QCEventQueryPaging paging,
                                              [FromQuery] QCEventQueryOptions options)
        {
            var validationData = _service.ValidateGetQCEvents(
                User, filter, sort, projection, paging, options);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var result = await _service.QueryQCEventDynamic(
                projection, options, Settings.Instance.QCEventImageFolderPath, filter, sort, paging);

            if (options.single_only && result == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            return(Ok(AppResult.Success(result)));
        }
        public IActionResult Update(int id, UpdateDeviceConfigModel model)
        {
            var entity = _service.DeviceConfigs.Id(id).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var validationData = _service.ValidateUpdateDeviceConfig(User, entity, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            _service.UpdateDeviceConfig(entity, model);
            context.SaveChanges();
            if (entity.IsCurrent)
            {
                Startup.SetCurrentConfig(entity);
            }
            return(NoContent());
        }
        public IActionResult GetDetail(string code,
                                       [FromQuery] RoomQueryProjection projection,
                                       [FromQuery] RoomQueryOptions options,
                                       bool hanging = false)
        {
            var checkerValid = projection.GetFieldsArr().Contains(RoomQueryProjection.CHECKER_VALID);

            projection = new RoomQueryProjection {
                fields = RoomQueryProjection.DETAIL
            };
            var entity = _service.Rooms.Code(code).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var validationData = _service.ValidateGetRoomDetail(entity, hanging, options);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            if (hanging)
            {
                _service.ReleaseHangingRoomByHangingUserId(UserId);
                _service.ChangeRoomHangingStatus(entity, true, UserId);
                context.SaveChanges();
            }
            var obj = _service.GetRoomDynamic(entity, projection, options);

            if (checkerValid)
            {
                var isRoomChecker = User.IsInRole(RoleName.ROOM_CHECKER);
                var valid         = _memberService.AreaMembers.OfArea(entity.BuildingAreaCode).Select(o => o.MemberId)
                                    .Contains(UserId) && isRoomChecker;
                obj["checker_valid"] = valid;
            }
            return(Ok(AppResult.Success(data: obj)));
        }
Exemple #14
0
        public async Task <IActionResult> Get([FromQuery][QueryObject] DepartmentQueryFilter filter,
                                              [FromQuery] DepartmentQuerySort sort,
                                              [FromQuery] Business.Models.DepartmentQueryProjection projection,
                                              [FromQuery] DepartmentQueryPaging paging,
                                              [FromQuery] DepartmentQueryOptions options)
        {
            var validationData = _service.ValidateGetDepartments(
                filter, sort, projection, paging, options);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var result = await _service.QueryDepartmentDynamic(
                projection, validationData.TempData, filter, sort, paging, options);

            if (options.single_only && result == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            return(Ok(AppResult.Success(data: result)));
        }
        public void OnActionExecuting(ActionExecutingContext context, object filter)
        {
            if (context.ModelState.IsValid || filter.ShouldSkip(context))
            {
                return;
            }

            var resultProvider = context.HttpContext.RequestServices.GetRequiredService <IValidationResultProvider>();

            var results = resultProvider.Results
                          .Where(o => !o.IsValid).SelectMany(o => o.Errors).MapTo <AppResult>().ToArray();

            var validationData = new ValidationData();

            validationData.Fail(results);

            var appResult = AppResult.FailValidation(validationData, validationData.Message);

            context.Result = new BadRequestObjectResult(appResult);

            context.HttpContext.Items[nameof(AutoValidateFilterHandler)] = true;
        }
        public IActionResult Update(int id, UpdateProductionBatchModel model)
        {
            var entity = _service.ProductionBatchs.Id(id).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var validationData = _service.ValidateUpdateProductionBatch(User, entity, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            _service.UpdateProductionBatch(entity, model);
            context.SaveChanges();
            // must be in transaction
            var ev = _ev_service.UpdateProductionBatch(entity, User);

            context.SaveChanges();
            return(NoContent());
        }
        public async Task <IActionResult> Get([FromQuery][QueryObject] ProductionBatchQueryFilter filter,
                                              [FromQuery] ProductionBatchQuerySort sort,
                                              [FromQuery] ProductionBatchQueryProjection projection,
                                              [FromQuery] ProductionBatchQueryPaging paging,
                                              [FromQuery] ProductionBatchQueryOptions options)
        {
            var validationData = _service.ValidateGetProductionBatchs(
                User, filter, sort, projection, paging, options);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var result = await _service.QueryProductionBatchDynamic(
                projection, options, filter, sort, paging);

            if (options.single_only && result == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            return(Ok(AppResult.Success(result)));
        }
        public IActionResult ChangeStatus(int id, ChangeQCDeviceStatusModel model)
        {
            var entity = _service.QCDevices.Id(id).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var validationData = _service.ValidateChangeQCDeviceStatus(User, entity, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            _service.ChangeQCDeviceStatus(entity, model);
            context.SaveChanges();
            // must be in transaction
            var ev = _ev_service.ChangeQCDeviceStatus(entity, User);

            context.SaveChanges();
            return(NoContent());
        }
        public IActionResult Create(CreateQCEventModel model)
        {
            var validationData = _service.ValidateCreateQCEvent(User, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            DateTime createdTime;

            createdTime = validationData.GetTempData <DateTime>(nameof(createdTime));
            var entity = _service.CreateQCEvent(model, createdTime);

            context.SaveChanges();
            if (Startup.KafkaProducer != null)
            {
                _service.ProduceEventToKafkaServer(Startup.KafkaProducer,
                                                   entity, Startup.CurrentConfig, Settings.Instance.QCEventImageFolderPath,
                                                   Constants.Paths.STATE_PATH);
            }
            return(Created($"/{Business.Constants.ApiEndpoint.RESOURCE_API}?id={entity.Id}",
                           AppResult.Success(entity.Id)));
        }
        public async Task <IActionResult> GetRoomBookings([FromQuery][QueryObject] BookingQueryFilter filter,
                                                          [FromQuery] BookingQuerySort sort,
                                                          [FromQuery] BookingQueryProjection projection,
                                                          [FromQuery] BookingQueryPaging paging,
                                                          [FromQuery] BookingQueryOptions options)
        {
            var validationData = _service.ValidateGetRoomBookings(
                User, filter, sort, projection, paging, options);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var result = await _service.QueryBookingDynamic(
                User, member : null, relationship : null,
                projection, validationData.TempData, filter, sort, paging, options);

            if (options.single_only && result == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            return(Ok(AppResult.Success(data: result)));
        }
        public async Task <IActionResult> GetManagedRequests([FromQuery][QueryObject] BookingQueryFilter filter,
                                                             [FromQuery] BookingQuerySort sort,
                                                             [FromQuery] BookingQueryProjection projection,
                                                             [FromQuery] BookingQueryPaging paging,
                                                             [FromQuery] BookingQueryOptions options)
        {
            var validationData = _service.ValidateGetBookings(
                User, BookingPrincipalRelationship.Manager, filter, sort, projection, paging, options);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var member = _memberService.Members.Id(UserId).FirstOrDefault();
            var result = await _service.QueryBookingDynamic(
                User, member, BookingPrincipalRelationship.Manager,
                projection, validationData.TempData, filter, sort, paging, options);

            if (options.single_only && result == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            return(Ok(AppResult.Success(data: result)));
        }
        public IActionResult GetLastEventTime()
        {
            var validationData = _service.ValidateGetLastEventTime(User);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            if (State.Instance.LastEventTime == null)
            {
                return(Ok(AppResult.Success()));
            }
            var time = State.Instance.LastEventTime.Value
                       .ToDefaultTimeZone();
            string defaultDf   = null;
            var    timeStr     = time.ToString(defaultDf);
            var    apiDateTime = new
            {
                display = timeStr,
                iso     = $"{time.ToUniversalTime():s}Z"
            };

            return(Ok(AppResult.Success(apiDateTime)));
        }
Exemple #23
0
        public IActionResult ChangeDefaultAppConfig(ChangeDefaultConfigModel model)
        {
            var entity = _service.AppConfigs.Id(model.ConfigId).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var validationData = _service.ValidateChangeDefaultConfig(User, entity, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var oldDefault = _service.AppConfigs.IsDefault().FirstOrDefault();

            _service.ChangeDefaultConfig(entity, oldDefault);
            context.SaveChanges();
            // must be in transaction
            var ev = _ev_service.ChangeDefaultAppConfig(entity, User);

            context.SaveChanges();
            return(NoContent());
        }
 public IActionResult Delete(string id)
 {
     try
     {
         var entity = _service.Users.Id(id).FirstOrDefault();
         if (entity == null)
         {
             return(NotFound(AppResult.NotFound()));
         }
         var validationData = _service.ValidateDeleteAppUser(User, entity);
         if (!validationData.IsValid)
         {
             return(BadRequest(AppResult.FailValidation(data: validationData)));
         }
         _service.DeleteAppUser(entity);
         context.SaveChanges();
         return(NoContent());
     }
     catch (DbUpdateException e)
     {
         _logger.Error(e);
         return(BadRequest(AppResult.DependencyDeleteFail()));
     }
 }
        public async Task <IActionResult> Update(string id, UpdateAppUserModel model)
        {
            var entity = _service.Users.Id(id).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var validationData = _service.ValidateUpdateAppUser(User, entity, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            _service.UpdateAppUser(entity, model);
            context.SaveChanges();
            var result = await _service.UpdatePasswordIfAvailable(entity, model);

            if (!result.Succeeded)
            {
                throw new Exception("Error change password");
            }
            return(NoContent());
        }
Exemple #26
0
        public async Task <IActionResult> LogIn(AuthorizationGrantModel model)
        {
            var validationData = _service.ValidateLogin(User, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            AppUser entity;

            switch (model.grant_type)
            {
            case "password":
            case null:
            {
                entity = await
                         _service.AuthenticateAsync(model.username, model.password);

                if (entity == null)
                {
                    return(Unauthorized(AppResult
                                        .Unauthorized(mess: "Invalid username or password")));
                }
            }
            break;

            case "refresh_token":
            {
                var validResult = _service.ValidateRefreshToken(model.refresh_token);
                if (validResult == null)
                {
                    return(Unauthorized(AppResult
                                        .Unauthorized(mess: "Invalid refresh token")));
                }
                entity = await _service.GetUserByIdAsync(validResult.Identity.Name);

                if (entity == null)
                {
                    return(Unauthorized(AppResult
                                        .Unauthorized(mess: "Invalid user identity")));
                }
            }
            break;

            case "firebase_token":
            {
                FirebaseToken validResult = await _service.ValidateFirebaseToken(model.firebase_token);

                if (validResult == null)
                {
                    return(Unauthorized(AppResult
                                        .Unauthorized(mess: "Invalid Firebase token")));
                }
                UserRecord userRecord = await FirebaseAuth.DefaultInstance.GetUserAsync(validResult.Uid);

                bool checkEmailDomain = _service.ValidateEmailDomain(userRecord.Email);
                if (!checkEmailDomain)
                {
                    return(Unauthorized(AppResult.InvalidEmailDomain()));
                }
                entity = await _service.GetUserByEmailAsync(userRecord.Email);

                var userExisted = entity != null;
                if (!userExisted || !entity.LoggedIn)
                {
                    using (var transaction = context.Database.BeginTransaction())
                    {
                        Member memberEntity;
                        if (!userExisted)
                        {
                            var emailInfo = userRecord.Email.GetEmailInfo();
                            entity = _service.ConvertToUser(userRecord, emailInfo.Item3);
                            var result = await _service
                                         .CreateUserWithoutPassAsync(entity);

                            if (!result.Succeeded)
                            {
                                foreach (var err in result.Errors)
                                {
                                    ModelState.AddModelError(err.Code, err.Description);
                                }
                                var builder = ResultHelper.MakeInvalidAccountRegistrationResults(ModelState);
                                return(BadRequest(builder));
                            }
                            _logger.CustomProperties(entity).Info("Register new user");
                            memberEntity = _memberService.ConvertToMember(entity, entity.MemberCode);
                            memberEntity = _memberService.CreateMember(memberEntity);
                        }
                        else
                        {
                            entity = _service.UpdateUser(entity, userRecord);
                            var result = await _service.UpdateUserAsync(entity);

                            if (!result.Succeeded)
                            {
                                foreach (var err in result.Errors)
                                {
                                    ModelState.AddModelError(err.Code, err.Description);
                                }
                                var builder = ResultHelper.MakeInvalidAccountRegistrationResults(ModelState);
                                return(BadRequest(builder));
                            }
                            memberEntity = _memberService.Members.Id(entity.Id).FirstOrDefault();
                            memberEntity = _memberService.UpdateMember(memberEntity, entity);
                        }
                        //log event
                        var ev = _sysService.GetEventForNewUser(
                            $"{memberEntity.Email} has logged into system for the first time",
                            memberEntity.UserId);
                        _sysService.CreateAppEvent(ev);
                        //end log event
                        context.SaveChanges();
                        transaction.Commit();
                    }
                }
            }
            break;

            default:
                return(BadRequest(AppResult.Unsupported("Unsupported grant type")));
            }
            var identity =
                await _service.GetIdentityAsync(entity, JwtBearerDefaults.AuthenticationScheme);

            var principal = new ClaimsPrincipal(identity);
            var utcNow    = DateTime.UtcNow;
            var props     = new AuthenticationProperties()
            {
                IssuedUtc  = utcNow,
                ExpiresUtc = utcNow.AddHours(WebApi.Settings.Instance.TokenValidHours)
            };

            props.Parameters["refresh_expires"] = utcNow.AddHours(
                WebApi.Settings.Instance.RefreshTokenValidHours);
            var resp = _service.GenerateTokenResponse(principal, props, model.scope ?? AppOAuthScope.ROLES);

            _logger.CustomProperties(entity).Info("Login user");
            return(Ok(resp));
        }
        public async Task <IActionResult> Create(CreateBookingModel model)
        {
            var memberQuery    = _memberService.Members;
            var member         = _memberService.Members.Id(UserId).FirstOrDefault();
            var validationData = _service.ValidateCreateBooking(User, member, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var      usingMemberIds = validationData.GetTempData <List <string> >("using_member_ids");
            var      bookedRoom = validationData.GetTempData <Room>("booked_room");
            AppEvent ev; Booking entity;

            using (var trans = context.Database.BeginTransaction())
            {
                entity = _service.CreateBooking(member, bookedRoom, model, usingMemberIds);
                var history = _service.CreateHistoryForCreateBooking(entity, member);
                _roomService.ChangeRoomHangingStatus(bookedRoom, false, UserId);
                //log event
                ev = _sysService.GetEventForBookingProcessing(history);
                _sysService.CreateAppEvent(ev);
                //end log event
                context.SaveChanges();
                trans.Commit();
            }
            //notify using members, managers (if any)
            var notiData = new Dictionary <string, string>
            {
                { "event", ev.Type },
                { "id", entity.Id.ToString() }
            };
            var notiMemberIds = usingMemberIds.Where(o => o != UserId).ToList();
            var notiMembers   = notiMemberIds.Any() ? NotiHelper.Notify(notiMemberIds, new Notification
            {
                Title = $"You have a new booking",
                Body  = $"{UserEmail} has just created a booking of room {entity.RoomCode} for you. Press for more detail"
            }, data: notiData) : Task.CompletedTask;
            var managerNoti = new Notification
            {
                Title = $"There's a new booking request",
                Body  = $"{UserEmail} has just created a booking of room {entity.RoomCode}. Press for more detail"
            };

            if (entity.Status == BookingStatusValues.PROCESSING)
            {
                var managerIds = _memberService.QueryManagersOfMember(member.UserId)
                                 .Select(o => o.UserId).ToList();
                if (managerIds.Count > 0)
                {
                    await NotiHelper.Notify(managerIds, managerNoti, data : notiData);
                }
            }
            else if (entity.Status == BookingStatusValues.VALID)
            {
                var managerIds = _memberService.QueryManagersOfArea(bookedRoom.BuildingAreaCode)
                                 .Select(o => o.UserId).ToList();
                if (managerIds.Count > 0)
                {
                    await NotiHelper.Notify(managerIds, managerNoti, data : notiData);
                }
            }
            await notiMembers;

            return(Created($"/{ApiEndpoint.BOOKING_API}/{entity.Id}",
                           AppResult.Success(data: entity.Id)));
        }
        public async Task <IActionResult> LogIn([FromForm] AuthorizationGrantModel model)
        {
            var validationData = _service.ValidateLogin(User, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            AppUser entity = null;

            switch (model.grant_type)
            {
            case "password":
            case null:
            {
                entity = await
                         _service.AuthenticateAsync(model.username, model.password);

                if (entity == null)
                {
                    return(Unauthorized(AppResult
                                        .Unauthorized(mess: "Invalid username or password")));
                }
            }
            break;

            case "refresh_token":
            {
                var validResult = _service.ValidateRefreshToken(model.refresh_token);
                if (validResult == null)
                {
                    return(Unauthorized(AppResult
                                        .Unauthorized(mess: "Invalid refresh token")));
                }
                entity = await _service.GetUserByIdAsync(validResult.Identity.Name);

                if (entity == null)
                {
                    return(Unauthorized(AppResult
                                        .Unauthorized(mess: "Invalid user identity")));
                }
            }
            break;

            default:
                return(BadRequest(AppResult
                                  .Unsupported("Unsupported grant type")));
            }
            var identity =
                await _service.GetIdentityAsync(entity, JwtBearerDefaults.AuthenticationScheme);

            var principal = new ClaimsPrincipal(identity);
            var utcNow    = DateTime.UtcNow;
            var props     = new AuthenticationProperties()
            {
                IssuedUtc  = utcNow,
                ExpiresUtc = utcNow.AddHours(WebApi.Settings.Instance.TokenValidHours)
            };

            props.Parameters["refresh_expires"] = utcNow.AddHours(
                WebApi.Settings.Instance.RefreshTokenValidHours);
            var resp = _service.GenerateTokenResponse(principal, props, model.scope);

            _logger.CustomProperties(entity).Info("Login user");
            return(Ok(resp));
        }
        public async Task <IActionResult> CancelBooking(int id, CancelBookingModel model)
        {
            var entity = _service.Bookings.Id(id).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var validationData = _service.ValidateCancelBooking(User, entity, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var      fromStatus = entity.Status;
            AppEvent ev;

            using (var trans = context.Database.BeginTransaction())
            {
                _service.CancelBooking(model, entity);
                var history = _service.CreateHistoryForCancelBooking(entity, fromStatus, entity.BookMember);
                //log event
                ev = _sysService.GetEventForBookingProcessing(history);
                _sysService.CreateAppEvent(ev);
                //end log event
                context.SaveChanges();
                trans.Commit();
            }
            //notify using members, managers (if any)
            var notiData = new Dictionary <string, string>
            {
                { "event", ev.Type },
                { "id", entity.Id.ToString() }
            };
            var notiMemberIds = entity.UsingMemberIds.Split('\n')
                                .Where(o => o != UserId).ToList();
            var notiMembers = notiMemberIds.Any() ? NotiHelper.Notify(notiMemberIds, new Notification
            {
                Title = $"Your booking {entity.Code} has been aborted",
                Body  = $"{UserEmail} has just aborted booking {entity.Code}. Press for more detail"
            }, data: notiData) : Task.CompletedTask;
            var managerNoti = new Notification
            {
                Title = $"A booking managed by you has been aborted",
                Body  = $"{UserEmail} has just aborted booking {entity.Code}. Press for more detail"
            };

            if (entity.Status == BookingStatusValues.VALID)
            {
                var managerIds = _memberService.QueryManagersOfMember(entity.BookMemberId)
                                 .Select(o => o.UserId).ToList();
                if (managerIds.Count > 0)
                {
                    await NotiHelper.Notify(managerIds, managerNoti, data : notiData);
                }
            }
            else if (entity.Status == BookingStatusValues.APPROVED)
            {
                var managerIds = _memberService.QueryManagersOfArea(entity.Room.BuildingAreaCode)
                                 .Select(o => o.UserId).ToList();
                if (managerIds.Count > 0)
                {
                    await NotiHelper.Notify(managerIds, managerNoti, data : notiData);
                }
            }
            await notiMembers;

            return(NoContent());
        }
        public async Task <IActionResult> ChangeApproveStatusOfBooking(int id, ChangeApprovalStatusOfBookingModel model)
        {
            var entity = _service.Bookings.Id(id).FirstOrDefault();

            if (entity == null)
            {
                return(NotFound(AppResult.NotFound()));
            }
            var member         = _memberService.Members.Id(UserId).FirstOrDefault();
            var validationData = _service.ValidateChangeApprovalStausOfBooking(User, member, entity, model);

            if (!validationData.IsValid)
            {
                return(BadRequest(AppResult.FailValidation(data: validationData)));
            }
            var      fromStatus = entity.Status;
            AppEvent ev;

            using (var trans = context.Database.BeginTransaction())
            {
                _service.ChangeApprovalStatusOfBooking(model, entity);
                var history = _service.CreateHistoryForChangeApprovalStatusOfBooking(
                    entity, fromStatus, model.IsApproved, member);
                //log event
                ev = _sysService.GetEventForBookingProcessing(history);
                _sysService.CreateAppEvent(ev);
                //end log event
                context.SaveChanges();
                trans.Commit();
            }
            //notify using members, managers (if any)
            var notiData = new Dictionary <string, string>
            {
                { "event", ev.Type },
                { "id", entity.Id.ToString() }
            };
            var approvePerson = fromStatus == BookingStatusValues.PROCESSING ? "department manager" :
                                "location manager";
            var action         = model.IsApproved ? "approved" : "denied";
            var usingMemberIds = entity.UsingMemberIds.Split('\n');
            var notiMemberIds  = usingMemberIds.Where(o => o != UserId).ToList();
            var notiMembers    = NotiHelper.Notify(notiMemberIds, new Notification
            {
                Title = $"Booking {entity.Code} has been {action} by your {approvePerson}",
                Body  = $"{UserEmail} has just {action} your booking. Press for more detail"
            }, data: notiData);

            if (entity.Status == BookingStatusValues.VALID && model.IsApproved)
            {
                var managerIds = _memberService.QueryManagersOfArea(entity.Room.BuildingAreaCode)
                                 .Select(o => o.UserId).ToList();
                if (managerIds.Count > 0)
                {
                    await NotiHelper.Notify(managerIds, new Notification
                    {
                        Title = $"There's a new booking request",
                        Body  = $"{UserEmail} has just {action} a booking of room {entity.RoomCode}. Press for more detail"
                    }, data : notiData);
                }
            }
            await notiMembers;

            return(NoContent());
        }