aboutsummaryrefslogtreecommitdiff
path: root/src/DevHive.Web
diff options
context:
space:
mode:
authorVictor S <57849063+transtrike@users.noreply.github.com>2021-02-05 10:54:49 -0800
committerGitHub <noreply@github.com>2021-02-05 10:54:49 -0800
commitf4a70c6430db923af9fa9958a11c2d6612cb52cc (patch)
treeca0ea403ba5500df20bc8854ec50529a25c64245 /src/DevHive.Web
parent1ccdefdac025b1b986ad2bd0bc3eda7505d6e7c3 (diff)
parent2269b5aa6c8d3dcb407c34fa256200bdc573585a (diff)
downloadDevHive-0.1.tar
DevHive-0.1.tar.gz
DevHive-0.1.zip
Merge pull request #18 from Team-Kaleidoscope/devv0.1
First stage: Complete. Awaiting further progress...
Diffstat (limited to 'src/DevHive.Web')
-rw-r--r--src/DevHive.Web/Attributes/GoodPasswordModelValidation.cs24
-rw-r--r--src/DevHive.Web/Attributes/OnlyLettersModelValidation.cs20
-rw-r--r--src/DevHive.Web/Configurations/Extensions/ConfigureAutoMapper.cs24
-rw-r--r--src/DevHive.Web/Configurations/Extensions/ConfigureDatabase.cs70
-rw-r--r--src/DevHive.Web/Configurations/Extensions/ConfigureDependencyInjection.cs38
-rw-r--r--src/DevHive.Web/Configurations/Extensions/ConfigureExceptionHandlerMiddleware.cs16
-rw-r--r--src/DevHive.Web/Configurations/Extensions/ConfigureJWT.cs54
-rw-r--r--src/DevHive.Web/Configurations/Extensions/ConfigureSwagger.cs23
-rw-r--r--src/DevHive.Web/Configurations/Mapping/CommentMappings.cs17
-rw-r--r--src/DevHive.Web/Configurations/Mapping/FeedMappings.cs18
-rw-r--r--src/DevHive.Web/Configurations/Mapping/LanguageMappings.cs23
-rw-r--r--src/DevHive.Web/Configurations/Mapping/PostMappings.cs17
-rw-r--r--src/DevHive.Web/Configurations/Mapping/RatingMappings.cs16
-rw-r--r--src/DevHive.Web/Configurations/Mapping/RoleMappings.cs21
-rw-r--r--src/DevHive.Web/Configurations/Mapping/TechnologyMappings.cs23
-rw-r--r--src/DevHive.Web/Configurations/Mapping/UserMappings.cs33
-rw-r--r--src/DevHive.Web/Controllers/CommentController.cs83
-rw-r--r--src/DevHive.Web/Controllers/FeedController.cs54
-rw-r--r--src/DevHive.Web/Controllers/LanguageController.cs87
-rw-r--r--src/DevHive.Web/Controllers/PostController.cs89
-rw-r--r--src/DevHive.Web/Controllers/RateController.cs40
-rw-r--r--src/DevHive.Web/Controllers/RoleController.cs77
-rw-r--r--src/DevHive.Web/Controllers/TechnologyController.cs87
-rw-r--r--src/DevHive.Web/Controllers/UserController.cs140
-rw-r--r--src/DevHive.Web/DevHive.Web.csproj40
-rw-r--r--src/DevHive.Web/Middleware/ExceptionMiddleware.cs50
-rw-r--r--src/DevHive.Web/Models/Comment/CreateCommentWebModel.cs17
-rw-r--r--src/DevHive.Web/Models/Comment/ReadCommentWebModel.cs21
-rw-r--r--src/DevHive.Web/Models/Comment/UpdateCommentWebModel.cs13
-rw-r--r--src/DevHive.Web/Models/Feed/GetPageWebModel.cs19
-rw-r--r--src/DevHive.Web/Models/Feed/ReadPageWebModel.cs10
-rw-r--r--src/DevHive.Web/Models/Identity/Role/CreateRoleWebModel.cs14
-rw-r--r--src/DevHive.Web/Models/Identity/Role/RoleWebModel.cs14
-rw-r--r--src/DevHive.Web/Models/Identity/Role/UpdateRoleWebModel.cs15
-rw-r--r--src/DevHive.Web/Models/Identity/User/BaseUserWebModel.cs34
-rw-r--r--src/DevHive.Web/Models/Identity/User/LoginWebModel.cs20
-rw-r--r--src/DevHive.Web/Models/Identity/User/ProfilePictureWebModel.cs7
-rw-r--r--src/DevHive.Web/Models/Identity/User/RegisterWebModel.cs14
-rw-r--r--src/DevHive.Web/Models/Identity/User/TokenWebModel.cs12
-rw-r--r--src/DevHive.Web/Models/Identity/User/UpdateProfilePictureWebModel.cs9
-rw-r--r--src/DevHive.Web/Models/Identity/User/UpdateUserWebModel.cs34
-rw-r--r--src/DevHive.Web/Models/Identity/User/UserWebModel.cs33
-rw-r--r--src/DevHive.Web/Models/Identity/User/UsernameWebModel.cs15
-rw-r--r--src/DevHive.Web/Models/Language/CreateLanguageWebModel.cs14
-rw-r--r--src/DevHive.Web/Models/Language/LanguageWebModel.cs13
-rw-r--r--src/DevHive.Web/Models/Language/ReadLanguageWebModel.cs11
-rw-r--r--src/DevHive.Web/Models/Language/UpdateLanguageWebModel.cs14
-rw-r--r--src/DevHive.Web/Models/Post/CreatePostWebModel.cs16
-rw-r--r--src/DevHive.Web/Models/Post/Rating/RatePostWebModel.cs11
-rw-r--r--src/DevHive.Web/Models/Post/Rating/ReadPostRatingWebModel.cs15
-rw-r--r--src/DevHive.Web/Models/Post/ReadPostWebModel.cs26
-rw-r--r--src/DevHive.Web/Models/Post/UpdatePostWebModel.cs21
-rw-r--r--src/DevHive.Web/Models/Technology/CreateTechnologyWebModel.cs14
-rw-r--r--src/DevHive.Web/Models/Technology/ReadTechnologyWebModel.cs11
-rw-r--r--src/DevHive.Web/Models/Technology/TechnologyWebModel.cs13
-rw-r--r--src/DevHive.Web/Models/Technology/UpdateTechnologyWebModel.cs15
-rw-r--r--src/DevHive.Web/Program.cs35
-rw-r--r--src/DevHive.Web/Properties/launchSettings.json67
-rw-r--r--src/DevHive.Web/Startup.cs129
-rw-r--r--src/DevHive.Web/appsettings.json30
60 files changed, 1808 insertions, 132 deletions
diff --git a/src/DevHive.Web/Attributes/GoodPasswordModelValidation.cs b/src/DevHive.Web/Attributes/GoodPasswordModelValidation.cs
new file mode 100644
index 0000000..7d6a1ea
--- /dev/null
+++ b/src/DevHive.Web/Attributes/GoodPasswordModelValidation.cs
@@ -0,0 +1,24 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace DevHive.Web.Attributes
+{
+ public class GoodPassword : ValidationAttribute
+ {
+ public override bool IsValid(object value)
+ {
+ var stringValue = (string)value;
+
+ for (int i = 0; i < stringValue.Length; i++)
+ {
+ if (Char.IsDigit(stringValue[i]))
+ {
+ base.ErrorMessage = "Password must be atleast 5 characters long!";
+ return stringValue.Length >= 5;
+ }
+ }
+ base.ErrorMessage = "Password must contain atleast 1 digit!";
+ return false;
+ }
+ }
+}
diff --git a/src/DevHive.Web/Attributes/OnlyLettersModelValidation.cs b/src/DevHive.Web/Attributes/OnlyLettersModelValidation.cs
new file mode 100644
index 0000000..07afee9
--- /dev/null
+++ b/src/DevHive.Web/Attributes/OnlyLettersModelValidation.cs
@@ -0,0 +1,20 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace DevHive.Web.Attributes
+{
+ public class OnlyLetters : ValidationAttribute
+ {
+ public override bool IsValid(object value)
+ {
+ var stringValue = (string)value;
+
+ foreach (char ch in stringValue)
+ {
+ if (!Char.IsLetter(ch))
+ return false;
+ }
+ return true;
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Extensions/ConfigureAutoMapper.cs b/src/DevHive.Web/Configurations/Extensions/ConfigureAutoMapper.cs
new file mode 100644
index 0000000..8b7d657
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Extensions/ConfigureAutoMapper.cs
@@ -0,0 +1,24 @@
+using System;
+using AutoMapper;
+//using AutoMapper.Configuration;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DevHive.Web.Configurations.Extensions
+{
+ public static class ConfigureAutoMapper
+ {
+ public static void AutoMapperConfiguration(this IServiceCollection services)
+ {
+ services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
+ }
+
+ public static void UseAutoMapperConfiguration(this IApplicationBuilder app)
+ {
+ var config = new MapperConfiguration(cfg =>
+ {
+ cfg.AllowNullCollections = true;
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/src/DevHive.Web/Configurations/Extensions/ConfigureDatabase.cs b/src/DevHive.Web/Configurations/Extensions/ConfigureDatabase.cs
new file mode 100644
index 0000000..9f02dd7
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Extensions/ConfigureDatabase.cs
@@ -0,0 +1,70 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using DevHive.Data.Models;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Builder;
+using System;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using DevHive.Data;
+
+namespace DevHive.Web.Configurations.Extensions
+{
+ public static class DatabaseExtensions
+ {
+ public static void DatabaseConfiguration(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddDbContext<DevHiveContext>(options =>
+ {
+ options.EnableSensitiveDataLogging(true);
+ options.UseNpgsql(configuration.GetConnectionString("DEV"));
+ });
+
+ services.AddIdentity<User, Role>()
+ .AddRoles<Role>()
+ .AddEntityFrameworkStores<DevHiveContext>();
+
+ services.Configure<IdentityOptions>(options =>
+ {
+ options.User.RequireUniqueEmail = true;
+
+ options.Password.RequireDigit = true;
+ options.Password.RequiredLength = 5;
+ options.Password.RequiredUniqueChars = 0;
+ options.Password.RequireLowercase = false;
+ options.Password.RequireNonAlphanumeric = false;
+ options.Password.RequireUppercase = false;
+
+ options.Lockout.AllowedForNewUsers = true;
+ options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
+ options.Lockout.MaxFailedAccessAttempts = 5;
+ });
+
+ services.AddAuthorization(options =>
+ {
+ options.AddPolicy("User", options =>
+ {
+ options.RequireAuthenticatedUser();
+ options.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
+ options.RequireRole("User");
+ });
+
+ options.AddPolicy("Administrator", options =>
+ {
+ options.RequireAuthenticatedUser();
+ options.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
+ options.RequireRole("Admin");
+ });
+ });
+ }
+
+ public static void UseDatabaseConfiguration(this IApplicationBuilder app)
+ {
+ app.UseHttpsRedirection();
+ app.UseRouting();
+
+ app.UseAuthentication();
+ app.UseAuthorization();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Extensions/ConfigureDependencyInjection.cs b/src/DevHive.Web/Configurations/Extensions/ConfigureDependencyInjection.cs
new file mode 100644
index 0000000..88f21d4
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Extensions/ConfigureDependencyInjection.cs
@@ -0,0 +1,38 @@
+using DevHive.Data.Interfaces.Repositories;
+using DevHive.Data.Repositories;
+using DevHive.Services.Interfaces;
+using DevHive.Services.Services;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DevHive.Web.Configurations.Extensions
+{
+ public static class ConfigureDependencyInjection
+ {
+ public static void DependencyInjectionConfiguration(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddTransient<ILanguageRepository, LanguageRepository>();
+ services.AddTransient<IRoleRepository, RoleRepository>();
+ services.AddTransient<ITechnologyRepository, TechnologyRepository>();
+ services.AddTransient<IUserRepository, UserRepository>();
+ services.AddTransient<IPostRepository, PostRepository>();
+ services.AddTransient<ICommentRepository, CommentRepository>();
+ services.AddTransient<IFeedRepository, FeedRepository>();
+ services.AddTransient<IRatingRepository, RatingRepository>();
+
+ services.AddTransient<ILanguageService, LanguageService>();
+ services.AddTransient<IRoleService, RoleService>();
+ services.AddTransient<ITechnologyService, TechnologyService>();
+ services.AddTransient<IUserService, UserService>();
+ services.AddTransient<IPostService, PostService>();
+ services.AddTransient<ICommentService, CommentService>();
+ services.AddTransient<IFeedService, FeedService>();
+ services.AddTransient<ICloudService, CloudinaryService>(options =>
+ new CloudinaryService(
+ cloudName: configuration.GetSection("Cloud").GetSection("cloudName").Value,
+ apiKey: configuration.GetSection("Cloud").GetSection("apiKey").Value,
+ apiSecret: configuration.GetSection("Cloud").GetSection("apiSecret").Value));
+ services.AddTransient<IRateService, RateService>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Extensions/ConfigureExceptionHandlerMiddleware.cs b/src/DevHive.Web/Configurations/Extensions/ConfigureExceptionHandlerMiddleware.cs
new file mode 100644
index 0000000..286727f
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Extensions/ConfigureExceptionHandlerMiddleware.cs
@@ -0,0 +1,16 @@
+using DevHive.Web.Middleware;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DevHive.Web.Configurations.Extensions
+{
+ public static class ConfigureExceptionHandlerMiddleware
+ {
+ public static void ExceptionHandlerMiddlewareConfiguration(this IServiceCollection services) { }
+
+ public static void UseExceptionHandlerMiddlewareConfiguration(this IApplicationBuilder app)
+ {
+ app.UseMiddleware<ExceptionMiddleware>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Extensions/ConfigureJWT.cs b/src/DevHive.Web/Configurations/Extensions/ConfigureJWT.cs
new file mode 100644
index 0000000..d422bc8
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Extensions/ConfigureJWT.cs
@@ -0,0 +1,54 @@
+using System.Text;
+using System.Threading.Tasks;
+using DevHive.Services.Options;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.IdentityModel.Tokens;
+
+namespace DevHive.Web.Configurations.Extensions
+{
+ public static class JWTExtensions
+ {
+ public static void JWTConfiguration(this IServiceCollection services, IConfiguration configuration)
+ {
+ services.AddSingleton(new JWTOptions(configuration
+ .GetSection("AppSettings")
+ .GetSection("Secret")
+ .Value));
+
+ // Get key from appsettings.json
+ var key = Encoding.ASCII.GetBytes(configuration
+ .GetSection("AppSettings")
+ .GetSection("Secret")
+ .Value);
+
+ // Setup Jwt Authentication
+ services.AddAuthentication(x =>
+ {
+ x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
+ x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+ })
+ .AddJwtBearer(x =>
+ {
+ x.Events = new JwtBearerEvents
+ {
+ OnTokenValidated = context =>
+ {
+ // TODO: add more authentication
+ return Task.CompletedTask;
+ }
+ };
+ x.RequireHttpsMetadata = false;
+ x.SaveToken = true;
+ x.TokenValidationParameters = new TokenValidationParameters
+ {
+ //ValidateIssuerSigningKey = false,
+ IssuerSigningKey = new SymmetricSecurityKey(key),
+ ValidateIssuer = false,
+ ValidateAudience = false
+ };
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/src/DevHive.Web/Configurations/Extensions/ConfigureSwagger.cs b/src/DevHive.Web/Configurations/Extensions/ConfigureSwagger.cs
new file mode 100644
index 0000000..a0641ab
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Extensions/ConfigureSwagger.cs
@@ -0,0 +1,23 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.OpenApi.Models;
+
+namespace DevHive.Web.Configurations.Extensions
+{
+ public static class SwaggerExtensions
+ {
+ public static void SwaggerConfiguration(this IServiceCollection services)
+ {
+ services.AddSwaggerGen(c =>
+ {
+ c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" });
+ });
+ }
+
+ public static void UseSwaggerConfiguration(this IApplicationBuilder app)
+ {
+ app.UseSwagger();
+ app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "API v1"));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/DevHive.Web/Configurations/Mapping/CommentMappings.cs b/src/DevHive.Web/Configurations/Mapping/CommentMappings.cs
new file mode 100644
index 0000000..b8d6829
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Mapping/CommentMappings.cs
@@ -0,0 +1,17 @@
+using AutoMapper;
+using DevHive.Services.Models.Comment;
+using DevHive.Web.Models.Comment;
+
+namespace DevHive.Web.Configurations.Mapping
+{
+ public class CommentMappings : Profile
+ {
+ public CommentMappings()
+ {
+ CreateMap<CreateCommentWebModel, CreateCommentServiceModel>();
+ CreateMap<UpdateCommentWebModel, UpdateCommentServiceModel>();
+
+ CreateMap<ReadCommentServiceModel, ReadCommentWebModel>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Mapping/FeedMappings.cs b/src/DevHive.Web/Configurations/Mapping/FeedMappings.cs
new file mode 100644
index 0000000..0909f6d
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Mapping/FeedMappings.cs
@@ -0,0 +1,18 @@
+using AutoMapper;
+using DevHive.Services.Models;
+using DevHive.Web.Models.Comment;
+using DevHive.Web.Models.Feed;
+
+namespace DevHive.Web.Configurations.Mapping
+{
+ public class FeedMappings : Profile
+ {
+ public FeedMappings()
+ {
+ CreateMap<GetPageWebModel, GetPageServiceModel>()
+ .ForMember(dest => dest.FirstRequestIssued, src => src.MapFrom(p => p.FirstPageTimeIssued));
+
+ CreateMap<ReadPageServiceModel, ReadPageWebModel>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Mapping/LanguageMappings.cs b/src/DevHive.Web/Configurations/Mapping/LanguageMappings.cs
new file mode 100644
index 0000000..eca0d1a
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Mapping/LanguageMappings.cs
@@ -0,0 +1,23 @@
+using AutoMapper;
+using DevHive.Web.Models.Language;
+using DevHive.Services.Models.Language;
+
+namespace DevHive.Web.Configurations.Mapping
+{
+ public class LanguageMappings : Profile
+ {
+ public LanguageMappings()
+ {
+ CreateMap<CreateLanguageWebModel, CreateLanguageServiceModel>();
+ CreateMap<ReadLanguageWebModel, ReadLanguageServiceModel>();
+ CreateMap<UpdateLanguageWebModel, UpdateLanguageServiceModel>()
+ .ForMember(src => src.Id, dest => dest.Ignore());
+ CreateMap<LanguageWebModel, LanguageServiceModel>();
+
+ CreateMap<LanguageServiceModel, LanguageWebModel>();
+ CreateMap<ReadLanguageServiceModel, ReadLanguageWebModel>();
+ CreateMap<CreateLanguageServiceModel, CreateLanguageWebModel>();
+ CreateMap<UpdateLanguageServiceModel, UpdateLanguageWebModel>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Mapping/PostMappings.cs b/src/DevHive.Web/Configurations/Mapping/PostMappings.cs
new file mode 100644
index 0000000..a5b46ee
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Mapping/PostMappings.cs
@@ -0,0 +1,17 @@
+using AutoMapper;
+using DevHive.Services.Models.Post;
+using DevHive.Web.Models.Post;
+
+namespace DevHive.Web.Configurations.Mapping
+{
+ public class PostMappings : Profile
+ {
+ public PostMappings()
+ {
+ CreateMap<CreatePostWebModel, CreatePostServiceModel>();
+ CreateMap<UpdatePostWebModel, UpdatePostServiceModel>();
+
+ CreateMap<ReadPostServiceModel, ReadPostWebModel>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Mapping/RatingMappings.cs b/src/DevHive.Web/Configurations/Mapping/RatingMappings.cs
new file mode 100644
index 0000000..4e071de
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Mapping/RatingMappings.cs
@@ -0,0 +1,16 @@
+using AutoMapper;
+using DevHive.Services.Models.Post.Rating;
+using DevHive.Web.Models.Post.Rating;
+
+namespace DevHive.Web.Configurations.Mapping
+{
+ public class RatingMappings : Profile
+ {
+ public RatingMappings()
+ {
+ CreateMap<RatePostWebModel, RatePostServiceModel>();
+
+ CreateMap<ReadPostRatingServiceModel, ReadPostRatingWebModel>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Mapping/RoleMappings.cs b/src/DevHive.Web/Configurations/Mapping/RoleMappings.cs
new file mode 100644
index 0000000..2ea2742
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Mapping/RoleMappings.cs
@@ -0,0 +1,21 @@
+using AutoMapper;
+using DevHive.Web.Models.Identity.Role;
+using DevHive.Services.Models.Identity.Role;
+
+namespace DevHive.Web.Configurations.Mapping
+{
+ public class RoleMappings : Profile
+ {
+ public RoleMappings()
+ {
+ CreateMap<CreateRoleWebModel, CreateRoleServiceModel>();
+ CreateMap<UpdateRoleWebModel, UpdateRoleServiceModel>()
+ .ForMember(src => src.Id, dest => dest.Ignore());
+ CreateMap<RoleWebModel, RoleServiceModel>();
+
+ CreateMap<CreateRoleServiceModel, CreateRoleWebModel>();
+ CreateMap<UpdateRoleServiceModel, UpdateRoleWebModel>();
+ CreateMap<RoleServiceModel, RoleWebModel>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Mapping/TechnologyMappings.cs b/src/DevHive.Web/Configurations/Mapping/TechnologyMappings.cs
new file mode 100644
index 0000000..708b6ac
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Mapping/TechnologyMappings.cs
@@ -0,0 +1,23 @@
+using AutoMapper;
+using DevHive.Web.Models.Technology;
+using DevHive.Services.Models.Technology;
+
+namespace DevHive.Web.Configurations.Mapping
+{
+ public class TechnologyMappings : Profile
+ {
+ public TechnologyMappings()
+ {
+ CreateMap<CreateTechnologyWebModel, CreateTechnologyServiceModel>();
+ CreateMap<ReadTechnologyWebModel, ReadTechnologyServiceModel>();
+ CreateMap<UpdateTechnologyWebModel, UpdateTechnologyServiceModel>()
+ .ForMember(src => src.Id, dest => dest.Ignore());
+ CreateMap<TechnologyWebModel, TechnologyServiceModel>();
+
+ CreateMap<CreateTechnologyServiceModel, CreateTechnologyWebModel>();
+ CreateMap<ReadTechnologyServiceModel, ReadTechnologyWebModel>();
+ CreateMap<UpdateTechnologyServiceModel, UpdateTechnologyWebModel>();
+ CreateMap<TechnologyServiceModel, TechnologyWebModel>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Configurations/Mapping/UserMappings.cs b/src/DevHive.Web/Configurations/Mapping/UserMappings.cs
new file mode 100644
index 0000000..f58e7ca
--- /dev/null
+++ b/src/DevHive.Web/Configurations/Mapping/UserMappings.cs
@@ -0,0 +1,33 @@
+using AutoMapper;
+using DevHive.Services.Models.Identity.User;
+using DevHive.Web.Models.Identity.User;
+using DevHive.Common.Models.Identity;
+
+namespace DevHive.Web.Configurations.Mapping
+{
+ public class UserMappings : Profile
+ {
+ public UserMappings()
+ {
+ CreateMap<LoginWebModel, LoginServiceModel>();
+ CreateMap<RegisterWebModel, RegisterServiceModel>();
+ CreateMap<UserWebModel, UserServiceModel>();
+ CreateMap<UpdateUserWebModel, UpdateUserServiceModel>();
+
+ CreateMap<UserServiceModel, UserWebModel>();
+
+ CreateMap<TokenModel, TokenWebModel>();
+
+ //Update
+ CreateMap<UpdateUserWebModel, UpdateUserServiceModel>();
+ CreateMap<UsernameWebModel, FriendServiceModel>();
+ CreateMap<UsernameWebModel, UpdateFriendServiceModel>();
+
+ CreateMap<UpdateProfilePictureWebModel, UpdateProfilePictureServiceModel>();
+ CreateMap<ProfilePictureServiceModel, ProfilePictureWebModel>();
+
+ CreateMap<UpdateUserServiceModel, UpdateUserWebModel>();
+ CreateMap<FriendServiceModel, UsernameWebModel>();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Controllers/CommentController.cs b/src/DevHive.Web/Controllers/CommentController.cs
new file mode 100644
index 0000000..c38e300
--- /dev/null
+++ b/src/DevHive.Web/Controllers/CommentController.cs
@@ -0,0 +1,83 @@
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using AutoMapper;
+using System;
+using DevHive.Web.Models.Comment;
+using DevHive.Services.Models.Comment;
+using Microsoft.AspNetCore.Authorization;
+using DevHive.Services.Interfaces;
+
+namespace DevHive.Web.Controllers
+{
+ [ApiController]
+ [Route("/api/[controller]")]
+ [Authorize(Roles = "User,Admin")]
+ public class CommentController
+ {
+ private readonly ICommentService _commentService;
+ private readonly IMapper _commentMapper;
+
+ public CommentController(ICommentService commentService, IMapper commentMapper)
+ {
+ this._commentService = commentService;
+ this._commentMapper = commentMapper;
+ }
+
+ [HttpPost]
+ public async Task<IActionResult> AddComment(Guid userId, [FromBody] CreateCommentWebModel createCommentWebModel, [FromHeader] string authorization)
+ {
+ if (!await this._commentService.ValidateJwtForCreating(userId, authorization))
+ return new UnauthorizedResult();
+
+ CreateCommentServiceModel createCommentServiceModel =
+ this._commentMapper.Map<CreateCommentServiceModel>(createCommentWebModel);
+ createCommentServiceModel.CreatorId = userId;
+
+ Guid id = await this._commentService.AddComment(createCommentServiceModel);
+
+ return id == Guid.Empty ?
+ new BadRequestObjectResult("Could not create comment!") :
+ new OkObjectResult(new { Id = id });
+ }
+
+ [HttpGet]
+ [AllowAnonymous]
+ public async Task<IActionResult> GetCommentById(Guid id)
+ {
+ ReadCommentServiceModel readCommentServiceModel = await this._commentService.GetCommentById(id);
+ ReadCommentWebModel readCommentWebModel = this._commentMapper.Map<ReadCommentWebModel>(readCommentServiceModel);
+
+ return new OkObjectResult(readCommentWebModel);
+ }
+
+ [HttpPut]
+ public async Task<IActionResult> UpdateComment(Guid userId, [FromBody] UpdateCommentWebModel updateCommentWebModel, [FromHeader] string authorization)
+ {
+ if (!await this._commentService.ValidateJwtForComment(updateCommentWebModel.CommentId, authorization))
+ return new UnauthorizedResult();
+
+ UpdateCommentServiceModel updateCommentServiceModel =
+ this._commentMapper.Map<UpdateCommentServiceModel>(updateCommentWebModel);
+ updateCommentServiceModel.CreatorId = userId;
+
+ Guid id = await this._commentService.UpdateComment(updateCommentServiceModel);
+
+ return id == Guid.Empty ?
+ new BadRequestObjectResult("Unable to update comment!") :
+ new OkObjectResult(new { Id = id });
+ }
+
+ [HttpDelete]
+ public async Task<IActionResult> DeleteComment(Guid id, [FromHeader] string authorization)
+ {
+ if (!await this._commentService.ValidateJwtForComment(id, authorization))
+ return new UnauthorizedResult();
+
+ return await this._commentService.DeleteComment(id) ?
+ new OkResult() :
+ new BadRequestObjectResult("Could not delete Comment");
+ }
+
+ }
+}
+
diff --git a/src/DevHive.Web/Controllers/FeedController.cs b/src/DevHive.Web/Controllers/FeedController.cs
new file mode 100644
index 0000000..abca3e4
--- /dev/null
+++ b/src/DevHive.Web/Controllers/FeedController.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Threading.Tasks;
+using AutoMapper;
+using DevHive.Services.Interfaces;
+using DevHive.Services.Models;
+using DevHive.Web.Models.Comment;
+using DevHive.Web.Models.Feed;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace DevHive.Web.Controllers
+{
+ [ApiController]
+ [Route("/api/[controller]")]
+ [Authorize(Roles = "User,Admin")]
+ public class FeedController
+ {
+ private readonly IFeedService _feedService;
+ private readonly IMapper _mapper;
+
+ public FeedController(IFeedService feedService, IMapper mapper)
+ {
+ this._feedService = feedService;
+ this._mapper = mapper;
+ }
+
+ [HttpPost]
+ [Route("GetPosts")]
+ public async Task<IActionResult> GetPosts(Guid userId, [FromBody] GetPageWebModel getPageWebModel)
+ {
+ GetPageServiceModel getPageServiceModel = this._mapper.Map<GetPageServiceModel>(getPageWebModel);
+ getPageServiceModel.UserId = userId;
+
+ ReadPageServiceModel readPageServiceModel = await this._feedService.GetPage(getPageServiceModel);
+ ReadPageWebModel readPageWebModel = this._mapper.Map<ReadPageWebModel>(readPageServiceModel);
+
+ return new OkObjectResult(readPageWebModel);
+ }
+
+ [HttpPost]
+ [Route("GetUserPosts")]
+ [AllowAnonymous]
+ public async Task<IActionResult> GetUserPosts(string username, [FromBody] GetPageWebModel getPageWebModel)
+ {
+ GetPageServiceModel getPageServiceModel = this._mapper.Map<GetPageServiceModel>(getPageWebModel);
+ getPageServiceModel.Username = username;
+
+ ReadPageServiceModel readPageServiceModel = await this._feedService.GetUserPage(getPageServiceModel);
+ ReadPageWebModel readPageWebModel = this._mapper.Map<ReadPageWebModel>(readPageServiceModel);
+
+ return new OkObjectResult(readPageWebModel);
+ }
+ }
+}
diff --git a/src/DevHive.Web/Controllers/LanguageController.cs b/src/DevHive.Web/Controllers/LanguageController.cs
new file mode 100644
index 0000000..5b0d5de
--- /dev/null
+++ b/src/DevHive.Web/Controllers/LanguageController.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using AutoMapper;
+using DevHive.Services.Interfaces;
+using DevHive.Services.Models.Language;
+using DevHive.Web.Models.Language;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace DevHive.Web.Controllers
+{
+ [ApiController]
+ [Route("/api/[controller]")]
+ public class LanguageController
+ {
+ private readonly ILanguageService _languageService;
+ private readonly IMapper _languageMapper;
+
+ public LanguageController(ILanguageService languageService, IMapper mapper)
+ {
+ this._languageService = languageService;
+ this._languageMapper = mapper;
+ }
+
+ [HttpPost]
+ [Authorize(Roles = "Admin")]
+ public async Task<IActionResult> Create([FromBody] CreateLanguageWebModel createLanguageWebModel)
+ {
+ CreateLanguageServiceModel languageServiceModel = this._languageMapper.Map<CreateLanguageServiceModel>(createLanguageWebModel);
+
+ Guid id = await this._languageService.CreateLanguage(languageServiceModel);
+
+ return id == Guid.Empty ?
+ new BadRequestObjectResult($"Could not create language {createLanguageWebModel.Name}") :
+ new OkObjectResult(new { Id = id });
+ }
+
+ [HttpGet]
+ [AllowAnonymous]
+ public async Task<IActionResult> GetById(Guid id)
+ {
+ ReadLanguageServiceModel languageServiceModel = await this._languageService.GetLanguageById(id);
+ ReadLanguageWebModel languageWebModel = this._languageMapper.Map<ReadLanguageWebModel>(languageServiceModel);
+
+ return new OkObjectResult(languageWebModel);
+ }
+
+ [HttpGet]
+ [Route("GetLanguages")]
+ [Authorize(Roles = "User,Admin")]
+ public IActionResult GetAllExistingLanguages()
+ {
+ HashSet<ReadLanguageServiceModel> languageServiceModels = this._languageService.GetLanguages();
+ HashSet<ReadLanguageWebModel> languageWebModels = this._languageMapper.Map<HashSet<ReadLanguageWebModel>>(languageServiceModels);
+
+ return new OkObjectResult(languageWebModels);
+ }
+
+ [HttpPut]
+ [Authorize(Roles = "Admin")]
+ public async Task<IActionResult> Update(Guid id, [FromBody] UpdateLanguageWebModel updateModel)
+ {
+ UpdateLanguageServiceModel updatelanguageServiceModel = this._languageMapper.Map<UpdateLanguageServiceModel>(updateModel);
+ updatelanguageServiceModel.Id = id;
+
+ bool result = await this._languageService.UpdateLanguage(updatelanguageServiceModel);
+
+ if (!result)
+ return new BadRequestObjectResult("Could not update Language");
+
+ return new OkResult();
+ }
+
+ [HttpDelete]
+ [Authorize(Roles = "Admin")]
+ public async Task<IActionResult> Delete(Guid id)
+ {
+ bool result = await this._languageService.DeleteLanguage(id);
+
+ if (!result)
+ return new BadRequestObjectResult("Could not delete Language");
+
+ return new OkResult();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Controllers/PostController.cs b/src/DevHive.Web/Controllers/PostController.cs
new file mode 100644
index 0000000..d3fdbf6
--- /dev/null
+++ b/src/DevHive.Web/Controllers/PostController.cs
@@ -0,0 +1,89 @@
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using AutoMapper;
+using System;
+using DevHive.Web.Models.Post;
+using DevHive.Services.Models.Post;
+using Microsoft.AspNetCore.Authorization;
+using DevHive.Services.Interfaces;
+
+namespace DevHive.Web.Controllers
+{
+ [ApiController]
+ [Route("/api/[controller]")]
+ [Authorize(Roles = "User,Admin")]
+ public class PostController
+ {
+ private readonly IPostService _postService;
+ private readonly IMapper _postMapper;
+
+ public PostController(IPostService postService, IMapper postMapper)
+ {
+ this._postService = postService;
+ this._postMapper = postMapper;
+ }
+
+ #region Create
+ [HttpPost]
+ public async Task<IActionResult> Create(Guid userId, [FromForm] CreatePostWebModel createPostWebModel, [FromHeader] string authorization)
+ {
+ if (!await this._postService.ValidateJwtForCreating(userId, authorization))
+ return new UnauthorizedResult();
+
+ CreatePostServiceModel createPostServiceModel =
+ this._postMapper.Map<CreatePostServiceModel>(createPostWebModel);
+ createPostServiceModel.CreatorId = userId;
+
+ Guid id = await this._postService.CreatePost(createPostServiceModel);
+
+ return id == Guid.Empty ?
+ new BadRequestObjectResult("Could not create post!") :
+ new OkObjectResult(new { Id = id });
+ }
+ #endregion
+
+ #region Read
+ [HttpGet]
+ [AllowAnonymous]
+ public async Task<IActionResult> GetById(Guid id)
+ {
+ ReadPostServiceModel postServiceModel = await this._postService.GetPostById(id);
+ ReadPostWebModel postWebModel = this._postMapper.Map<ReadPostWebModel>(postServiceModel);
+
+ return new OkObjectResult(postWebModel);
+ }
+ #endregion
+
+ #region Update
+ [HttpPut]
+ public async Task<IActionResult> Update(Guid userId, [FromForm] UpdatePostWebModel updatePostWebModel, [FromHeader] string authorization)
+ {
+ if (!await this._postService.ValidateJwtForPost(updatePostWebModel.PostId, authorization))
+ return new UnauthorizedResult();
+
+ UpdatePostServiceModel updatePostServiceModel =
+ this._postMapper.Map<UpdatePostServiceModel>(updatePostWebModel);
+ updatePostServiceModel.CreatorId = userId;
+
+ Guid id = await this._postService.UpdatePost(updatePostServiceModel);
+
+ return id == Guid.Empty ?
+ new BadRequestObjectResult("Could not update post!") :
+ new OkObjectResult(new { Id = id });
+ }
+ #endregion
+
+ #region Delete
+ [HttpDelete]
+ public async Task<IActionResult> Delete(Guid id, [FromHeader] string authorization)
+ {
+ if (!await this._postService.ValidateJwtForPost(id, authorization))
+ return new UnauthorizedResult();
+
+ return await this._postService.DeletePost(id) ?
+ new OkResult() :
+ new BadRequestObjectResult("Could not delete Post");
+ }
+ #endregion
+ }
+}
diff --git a/src/DevHive.Web/Controllers/RateController.cs b/src/DevHive.Web/Controllers/RateController.cs
new file mode 100644
index 0000000..68b859b
--- /dev/null
+++ b/src/DevHive.Web/Controllers/RateController.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Threading.Tasks;
+using AutoMapper;
+using DevHive.Services.Interfaces;
+using DevHive.Services.Models.Post.Rating;
+using DevHive.Web.Models.Post.Rating;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace DevHive.Web.Controllers
+{
+ [ApiController]
+ [Route("api/[controller]")]
+ public class RateController
+ {
+ private readonly IRateService _rateService;
+ private readonly IUserService _userService;
+ private readonly IMapper _mapper;
+
+ public RateController(IRateService rateService, IUserService userService, IMapper mapper)
+ {
+ this._rateService = rateService;
+ this._userService = userService;
+ this._mapper = mapper;
+ }
+
+ [HttpPost]
+ [Authorize(Roles = "Admin,User")]
+ public async Task<IActionResult> RatePost(Guid userId, [FromBody] RatePostWebModel ratePostWebModel, [FromHeader] string authorization)
+ {
+ RatePostServiceModel ratePostServiceModel = this._mapper.Map<RatePostServiceModel>(ratePostWebModel);
+ ratePostServiceModel.UserId = userId;
+
+ ReadPostRatingServiceModel readPostRatingServiceModel = await this._rateService.RatePost(ratePostServiceModel);
+ ReadPostRatingWebModel readPostRatingWebModel = this._mapper.Map<ReadPostRatingWebModel>(readPostRatingServiceModel);
+
+ return new OkObjectResult(readPostRatingWebModel);
+ }
+ }
+}
diff --git a/src/DevHive.Web/Controllers/RoleController.cs b/src/DevHive.Web/Controllers/RoleController.cs
new file mode 100644
index 0000000..0d2a2eb
--- /dev/null
+++ b/src/DevHive.Web/Controllers/RoleController.cs
@@ -0,0 +1,77 @@
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using DevHive.Web.Models.Identity.Role;
+using AutoMapper;
+using System;
+using DevHive.Services.Interfaces;
+using DevHive.Services.Models.Identity.Role;
+using Microsoft.AspNetCore.Authorization;
+
+namespace DevHive.Web.Controllers
+{
+ [ApiController]
+ [Route("/api/[controller]")]
+ public class RoleController
+ {
+ private readonly IRoleService _roleService;
+ private readonly IMapper _roleMapper;
+
+ public RoleController(IRoleService roleService, IMapper mapper)
+ {
+ this._roleService = roleService;
+ this._roleMapper = mapper;
+ }
+
+ [HttpPost]
+ [Authorize(Roles = "Admin")]
+ public async Task<IActionResult> Create([FromBody] CreateRoleWebModel createRoleWebModel)
+ {
+ CreateRoleServiceModel roleServiceModel =
+ this._roleMapper.Map<CreateRoleServiceModel>(createRoleWebModel);
+
+ Guid id = await this._roleService.CreateRole(roleServiceModel);
+
+ return id == Guid.Empty ?
+ new BadRequestObjectResult($"Could not create role {createRoleWebModel.Name}") :
+ new OkObjectResult(new { Id = id });
+ }
+
+ [HttpGet]
+ [Authorize(Roles = "User,Admin")]
+ public async Task<IActionResult> GetById(Guid id)
+ {
+ RoleServiceModel roleServiceModel = await this._roleService.GetRoleById(id);
+ RoleWebModel roleWebModel = this._roleMapper.Map<RoleWebModel>(roleServiceModel);
+
+ return new OkObjectResult(roleWebModel);
+ }
+
+ [HttpPut]
+ [Authorize(Roles = "Admin")]
+ public async Task<IActionResult> Update(Guid id, [FromBody] UpdateRoleWebModel updateRoleWebModel)
+ {
+ UpdateRoleServiceModel updateRoleServiceModel =
+ this._roleMapper.Map<UpdateRoleServiceModel>(updateRoleWebModel);
+ updateRoleServiceModel.Id = id;
+
+ bool result = await this._roleService.UpdateRole(updateRoleServiceModel);
+
+ if (!result)
+ return new BadRequestObjectResult("Could not update role!");
+
+ return new OkResult();
+ }
+
+ [HttpDelete]
+ [Authorize(Roles = "Admin")]
+ public async Task<IActionResult> Delete(Guid id)
+ {
+ bool result = await this._roleService.DeleteRole(id);
+
+ if (!result)
+ return new BadRequestObjectResult("Could not delete role!");
+
+ return new OkResult();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Controllers/TechnologyController.cs b/src/DevHive.Web/Controllers/TechnologyController.cs
new file mode 100644
index 0000000..e507899
--- /dev/null
+++ b/src/DevHive.Web/Controllers/TechnologyController.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using AutoMapper;
+using DevHive.Services.Interfaces;
+using DevHive.Services.Models.Technology;
+using DevHive.Web.Models.Technology;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace DevHive.Web.Controllers
+{
+ [ApiController]
+ [Route("/api/[controller]")]
+ public class TechnologyController
+ {
+ private readonly ITechnologyService _technologyService;
+ private readonly IMapper _technologyMapper;
+
+ public TechnologyController(ITechnologyService technologyService, IMapper technologyMapper)
+ {
+ this._technologyService = technologyService;
+ this._technologyMapper = technologyMapper;
+ }
+
+ [HttpPost]
+ [Authorize(Roles = "Admin")]
+ public async Task<IActionResult> Create([FromBody] CreateTechnologyWebModel createTechnologyWebModel)
+ {
+ CreateTechnologyServiceModel technologyServiceModel = this._technologyMapper.Map<CreateTechnologyServiceModel>(createTechnologyWebModel);
+
+ Guid id = await this._technologyService.CreateTechnology(technologyServiceModel);
+
+ return id == Guid.Empty ?
+ new BadRequestObjectResult($"Could not create technology {createTechnologyWebModel.Name}") :
+ new OkObjectResult(new { Id = id });
+ }
+
+ [HttpGet]
+ [AllowAnonymous]
+ public async Task<IActionResult> GetById(Guid id)
+ {
+ ReadTechnologyServiceModel readTechnologyServiceModel = await this._technologyService.GetTechnologyById(id);
+ ReadTechnologyWebModel readTechnologyWebModel = this._technologyMapper.Map<ReadTechnologyWebModel>(readTechnologyServiceModel);
+
+ return new OkObjectResult(readTechnologyWebModel);
+ }
+
+ [HttpGet]
+ [Route("GetTechnologies")]
+ [Authorize(Roles = "User,Admin")]
+ public IActionResult GetAllExistingTechnologies()
+ {
+ HashSet<ReadTechnologyServiceModel> technologyServiceModels = this._technologyService.GetTechnologies();
+ HashSet<ReadTechnologyWebModel> languageWebModels = this._technologyMapper.Map<HashSet<ReadTechnologyWebModel>>(technologyServiceModels);
+
+ return new OkObjectResult(languageWebModels);
+ }
+
+ [HttpPut]
+ [Authorize(Roles = "Admin")]
+ public async Task<IActionResult> Update(Guid id, [FromBody] UpdateTechnologyWebModel updateModel)
+ {
+ UpdateTechnologyServiceModel updateTechnologyServiceModel = this._technologyMapper.Map<UpdateTechnologyServiceModel>(updateModel);
+ updateTechnologyServiceModel.Id = id;
+
+ bool result = await this._technologyService.UpdateTechnology(updateTechnologyServiceModel);
+
+ if (!result)
+ return new BadRequestObjectResult("Could not update Technology");
+
+ return new OkResult();
+ }
+
+ [HttpDelete]
+ [Authorize(Roles = "Admin")]
+ public async Task<IActionResult> Delete(Guid id)
+ {
+ bool result = await this._technologyService.DeleteTechnology(id);
+
+ if (!result)
+ return new BadRequestObjectResult("Could not delete Technology");
+
+ return new OkResult();
+ }
+ }
+}
diff --git a/src/DevHive.Web/Controllers/UserController.cs b/src/DevHive.Web/Controllers/UserController.cs
new file mode 100644
index 0000000..109bbaa
--- /dev/null
+++ b/src/DevHive.Web/Controllers/UserController.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Threading.Tasks;
+using AutoMapper;
+using DevHive.Services.Models.Identity.User;
+using DevHive.Web.Models.Identity.User;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using DevHive.Common.Models.Identity;
+using DevHive.Services.Interfaces;
+using Microsoft.Extensions.Hosting;
+
+namespace DevHive.Web.Controllers
+{
+ [ApiController]
+ [Route("/api/[controller]")]
+ public class UserController : ControllerBase
+ {
+ private readonly IUserService _userService;
+ private readonly IMapper _userMapper;
+
+ public UserController(IUserService userService, IMapper mapper)
+ {
+ this._userService = userService;
+ this._userMapper = mapper;
+ }
+
+ #region Authentication
+ [HttpPost]
+ [Route("Login")]
+ [AllowAnonymous]
+ public async Task<IActionResult> Login([FromBody] LoginWebModel loginModel)
+ {
+ LoginServiceModel loginServiceModel = this._userMapper.Map<LoginServiceModel>(loginModel);
+
+ TokenModel TokenModel = await this._userService.LoginUser(loginServiceModel);
+ TokenWebModel tokenWebModel = this._userMapper.Map<TokenWebModel>(TokenModel);
+
+ return new OkObjectResult(tokenWebModel);
+ }
+
+ [HttpPost]
+ [Route("Register")]
+ [AllowAnonymous]
+ public async Task<IActionResult> Register([FromBody] RegisterWebModel registerModel)
+ {
+ RegisterServiceModel registerServiceModel = this._userMapper.Map<RegisterServiceModel>(registerModel);
+
+ TokenModel TokenModel = await this._userService.RegisterUser(registerServiceModel);
+ TokenWebModel tokenWebModel = this._userMapper.Map<TokenWebModel>(TokenModel);
+
+ return new CreatedResult("Register", tokenWebModel);
+ }
+ #endregion
+
+ #region Read
+ [HttpGet]
+ [Authorize(Roles = "User,Admin")]
+ public async Task<IActionResult> GetById(Guid id, [FromHeader] string authorization)
+ {
+ if (!await this._userService.ValidJWT(id, authorization))
+ return new UnauthorizedResult();
+
+ UserServiceModel userServiceModel = await this._userService.GetUserById(id);
+ UserWebModel userWebModel = this._userMapper.Map<UserWebModel>(userServiceModel);
+
+ return new OkObjectResult(userWebModel);
+ }
+
+ [HttpGet]
+ [Route("GetUser")]
+ [AllowAnonymous]
+ public async Task<IActionResult> GetUser(string username)
+ {
+ UserServiceModel friendServiceModel = await this._userService.GetUserByUsername(username);
+ UserWebModel friend = this._userMapper.Map<UserWebModel>(friendServiceModel);
+
+ return new OkObjectResult(friend);
+ }
+ #endregion
+
+ #region Update
+ [HttpPut]
+ [Authorize(Roles = "User,Admin")]
+ public async Task<IActionResult> Update(Guid id, [FromBody] UpdateUserWebModel updateUserWebModel, [FromHeader] string authorization)
+ {
+ if (!await this._userService.ValidJWT(id, authorization))
+ return new UnauthorizedResult();
+
+ UpdateUserServiceModel updateUserServiceModel = this._userMapper.Map<UpdateUserServiceModel>(updateUserWebModel);
+ updateUserServiceModel.Id = id;
+
+ UserServiceModel userServiceModel = await this._userService.UpdateUser(updateUserServiceModel);
+ UserWebModel userWebModel = this._userMapper.Map<UserWebModel>(userServiceModel);
+
+ return new AcceptedResult("UpdateUser", userWebModel);
+ }
+
+ [HttpPut]
+ [Route("ProfilePicture")]
+ [Authorize(Roles = "User,Admin")]
+ public async Task<IActionResult> UpdateProfilePicture(Guid userId, [FromForm] UpdateProfilePictureWebModel updateProfilePictureWebModel, [FromHeader] string authorization)
+ {
+ if (!await this._userService.ValidJWT(userId, authorization))
+ return new UnauthorizedResult();
+
+ UpdateProfilePictureServiceModel updateProfilePictureServiceModel = this._userMapper.Map<UpdateProfilePictureServiceModel>(updateProfilePictureWebModel);
+ updateProfilePictureServiceModel.UserId = userId;
+
+ ProfilePictureServiceModel profilePictureServiceModel = await this._userService.UpdateProfilePicture(updateProfilePictureServiceModel);
+ ProfilePictureWebModel profilePictureWebModel = this._userMapper.Map<ProfilePictureWebModel>(profilePictureServiceModel);
+
+ return new AcceptedResult("UpdateProfilePicture", profilePictureWebModel);
+ }
+ #endregion
+
+ #region Delete
+ [HttpDelete]
+ [Authorize(Roles = "User,Admin")]
+ public async Task<IActionResult> Delete(Guid id, [FromHeader] string authorization)
+ {
+ if (!await this._userService.ValidJWT(id, authorization))
+ return new UnauthorizedResult();
+
+ bool result = await this._userService.DeleteUser(id);
+ if (!result)
+ return new BadRequestObjectResult("Could not delete User");
+
+ return new OkResult();
+ }
+ #endregion
+
+ [HttpPost]
+ [Authorize(Roles = "User,Admin")]
+ [Route("SuperSecretPromotionToAdmin")]
+ public async Task<IActionResult> SuperSecretPromotionToAdmin(Guid userId)
+ {
+ return new OkObjectResult(await this._userService.SuperSecretPromotionToAdmin(userId));
+ }
+ }
+}
diff --git a/src/DevHive.Web/DevHive.Web.csproj b/src/DevHive.Web/DevHive.Web.csproj
index 218b809..0aa2831 100644
--- a/src/DevHive.Web/DevHive.Web.csproj
+++ b/src/DevHive.Web/DevHive.Web.csproj
@@ -1,13 +1,27 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
-
- <PropertyGroup>
- <TargetFramework>net5.0</TargetFramework>
- </PropertyGroup>
-
- <ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.1" NoWarn="NU1605" />
- <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.1" NoWarn="NU1605" />
- <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
- </ItemGroup>
-
-</Project>
+<Project Sdk="Microsoft.NET.Sdk.Web">
+ <PropertyGroup>
+ <TargetFramework>net5.0</TargetFramework>
+ </PropertyGroup>
+ <PropertyGroup>
+ <EnableNETAnalyzers>true</EnableNETAnalyzers>
+ <AnalysisLevel>latest</AnalysisLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.1" NoWarn="NU1605"/>
+ <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.1" NoWarn="NU1605"/>
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.1">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.1"/>
+ <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3"/>
+ <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0"/>
+ <PackageReference Include="AutoMapper" Version="10.1.1"/>
+ <PackageReference Include="Newtonsoft.Json" Version="12.0.3"/>
+ <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.1"/>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\DevHive.Services\DevHive.Services.csproj"/>
+ <ProjectReference Include="..\DevHive.Common\DevHive.Common.csproj"/>
+ </ItemGroup>
+</Project>
diff --git a/src/DevHive.Web/Middleware/ExceptionMiddleware.cs b/src/DevHive.Web/Middleware/ExceptionMiddleware.cs
new file mode 100644
index 0000000..cb6d4ca
--- /dev/null
+++ b/src/DevHive.Web/Middleware/ExceptionMiddleware.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Net;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
+
+namespace DevHive.Web.Middleware
+{
+ public class ExceptionMiddleware
+ {
+ private readonly RequestDelegate _next;
+ // private readonly ILogger _logger;
+
+ public ExceptionMiddleware(RequestDelegate next)
+ {
+ this._next = next;
+ // this._logger = logger;
+ }
+ // public ExceptionMiddleware(RequestDelegate next, ILogger logger)
+ // {
+ // this._logger = logger;
+ // this._next = next;
+ // }
+
+ public async Task InvokeAsync(HttpContext httpContext)
+ {
+ try
+ {
+ await this._next(httpContext);
+ }
+ catch (Exception ex)
+ {
+ // this._logger.LogError($"Something went wrong: {ex}");
+ await HandleExceptionAsync(httpContext, ex);
+ }
+ }
+
+ private Task HandleExceptionAsync(HttpContext context, Exception exception)
+ {
+ context.Response.ContentType = "application/json";
+ context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
+
+ return context.Response.WriteAsync(new
+ {
+ StatusCode = context.Response.StatusCode,
+ Message = exception.Message
+ }.ToString());
+ }
+ }
+}
diff --git a/src/DevHive.Web/Models/Comment/CreateCommentWebModel.cs b/src/DevHive.Web/Models/Comment/CreateCommentWebModel.cs
new file mode 100644
index 0000000..8b2bf8d
--- /dev/null
+++ b/src/DevHive.Web/Models/Comment/CreateCommentWebModel.cs
@@ -0,0 +1,17 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Comment
+{
+ public class CreateCommentWebModel
+ {
+ [NotNull]
+ [Required]
+ public Guid PostId { get; set; }
+
+ [NotNull]
+ [Required]
+ public string Message { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Comment/ReadCommentWebModel.cs b/src/DevHive.Web/Models/Comment/ReadCommentWebModel.cs
new file mode 100644
index 0000000..4d3aff7
--- /dev/null
+++ b/src/DevHive.Web/Models/Comment/ReadCommentWebModel.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace DevHive.Web.Models.Comment
+{
+ public class ReadCommentWebModel
+ {
+ public Guid CommentId { get; set; }
+
+ public Guid PostId { get; set; }
+
+ public string IssuerFirstName { get; set; }
+
+ public string IssuerLastName { get; set; }
+
+ public string IssuerUsername { get; set; }
+
+ public string Message { get; set; }
+
+ public DateTime TimeCreated { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Comment/UpdateCommentWebModel.cs b/src/DevHive.Web/Models/Comment/UpdateCommentWebModel.cs
new file mode 100644
index 0000000..b5d7970
--- /dev/null
+++ b/src/DevHive.Web/Models/Comment/UpdateCommentWebModel.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace DevHive.Web.Models.Comment
+{
+ public class UpdateCommentWebModel
+ {
+ public Guid CommentId { get; set; }
+
+ public Guid PostId { get; set; }
+
+ public string NewMessage { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Feed/GetPageWebModel.cs b/src/DevHive.Web/Models/Feed/GetPageWebModel.cs
new file mode 100644
index 0000000..4ea44cc
--- /dev/null
+++ b/src/DevHive.Web/Models/Feed/GetPageWebModel.cs
@@ -0,0 +1,19 @@
+using System;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+
+namespace DevHive.Web.Models.Feed
+{
+ public class GetPageWebModel
+ {
+ [Range(1, int.MaxValue)]
+ public int PageNumber { get; set; }
+
+ [Required]
+ public DateTime FirstPageTimeIssued { get; set; }
+
+ [DefaultValue(5)]
+ [Range(1, int.MaxValue)]
+ public int PageSize { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Feed/ReadPageWebModel.cs b/src/DevHive.Web/Models/Feed/ReadPageWebModel.cs
new file mode 100644
index 0000000..f429313
--- /dev/null
+++ b/src/DevHive.Web/Models/Feed/ReadPageWebModel.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using DevHive.Web.Models.Post;
+
+namespace DevHive.Web.Models.Comment
+{
+ public class ReadPageWebModel
+ {
+ public List<ReadPostWebModel> Posts { get; set; } = new();
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/Role/CreateRoleWebModel.cs b/src/DevHive.Web/Models/Identity/Role/CreateRoleWebModel.cs
new file mode 100644
index 0000000..859cdd9
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/Role/CreateRoleWebModel.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Identity.Role
+{
+ public class CreateRoleWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string Name { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/Role/RoleWebModel.cs b/src/DevHive.Web/Models/Identity/Role/RoleWebModel.cs
new file mode 100644
index 0000000..99b0f50
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/Role/RoleWebModel.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Identity.Role
+{
+ public class RoleWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string Name { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/Role/UpdateRoleWebModel.cs b/src/DevHive.Web/Models/Identity/Role/UpdateRoleWebModel.cs
new file mode 100644
index 0000000..3870481
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/Role/UpdateRoleWebModel.cs
@@ -0,0 +1,15 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Identity.Role
+{
+ public class UpdateRoleWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string Name { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/User/BaseUserWebModel.cs b/src/DevHive.Web/Models/Identity/User/BaseUserWebModel.cs
new file mode 100644
index 0000000..297e1a5
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/User/BaseUserWebModel.cs
@@ -0,0 +1,34 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using DevHive.Web.Attributes;
+
+namespace DevHive.Web.Models.Identity.User
+{
+ public class BaseUserWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string UserName { get; set; }
+
+ [NotNull]
+ [Required]
+ [EmailAddress]
+ public string Email { get; set; }
+
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(30)]
+ [OnlyLetters(ErrorMessage = "First name can only contain letters!")]
+ public string FirstName { get; set; }
+
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(30)]
+ [OnlyLetters(ErrorMessage = "Last name can only contain letters!")]
+ public string LastName { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/User/LoginWebModel.cs b/src/DevHive.Web/Models/Identity/User/LoginWebModel.cs
new file mode 100644
index 0000000..ccd806f
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/User/LoginWebModel.cs
@@ -0,0 +1,20 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using DevHive.Web.Attributes;
+
+namespace DevHive.Web.Models.Identity.User
+{
+ public class LoginWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string UserName { get; set; }
+
+ [NotNull]
+ [Required]
+ [GoodPassword]
+ public string Password { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/User/ProfilePictureWebModel.cs b/src/DevHive.Web/Models/Identity/User/ProfilePictureWebModel.cs
new file mode 100644
index 0000000..9fb1516
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/User/ProfilePictureWebModel.cs
@@ -0,0 +1,7 @@
+namespace DevHive.Web.Models.Identity.User
+{
+ public class ProfilePictureWebModel
+ {
+ public string ProfilePictureURL { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/User/RegisterWebModel.cs b/src/DevHive.Web/Models/Identity/User/RegisterWebModel.cs
new file mode 100644
index 0000000..0fc7ec6
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/User/RegisterWebModel.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using DevHive.Web.Attributes;
+
+namespace DevHive.Web.Models.Identity.User
+{
+ public class RegisterWebModel : BaseUserWebModel
+ {
+ [NotNull]
+ [Required]
+ [GoodPassword]
+ public string Password { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/User/TokenWebModel.cs b/src/DevHive.Web/Models/Identity/User/TokenWebModel.cs
new file mode 100644
index 0000000..154b64b
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/User/TokenWebModel.cs
@@ -0,0 +1,12 @@
+namespace DevHive.Web.Models.Identity.User
+{
+ public class TokenWebModel
+ {
+ public TokenWebModel(string token)
+ {
+ this.Token = token;
+ }
+
+ public string Token { get; set; }
+ }
+} \ No newline at end of file
diff --git a/src/DevHive.Web/Models/Identity/User/UpdateProfilePictureWebModel.cs b/src/DevHive.Web/Models/Identity/User/UpdateProfilePictureWebModel.cs
new file mode 100644
index 0000000..6efe968
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/User/UpdateProfilePictureWebModel.cs
@@ -0,0 +1,9 @@
+using Microsoft.AspNetCore.Http;
+
+namespace DevHive.Web.Models.Identity.User
+{
+ public class UpdateProfilePictureWebModel
+ {
+ public IFormFile Picture { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/User/UpdateUserWebModel.cs b/src/DevHive.Web/Models/Identity/User/UpdateUserWebModel.cs
new file mode 100644
index 0000000..62901f6
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/User/UpdateUserWebModel.cs
@@ -0,0 +1,34 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using DevHive.Web.Attributes;
+using DevHive.Web.Models.Identity.Role;
+using DevHive.Web.Models.Language;
+using DevHive.Web.Models.Technology;
+
+namespace DevHive.Web.Models.Identity.User
+{
+ public class UpdateUserWebModel : BaseUserWebModel
+ {
+ [NotNull]
+ [Required]
+ [GoodPassword]
+ public string Password { get; set; }
+
+ [NotNull]
+ [Required]
+ public HashSet<UsernameWebModel> Friends { get; set; }
+
+ [NotNull]
+ [Required]
+ public HashSet<UpdateRoleWebModel> Roles { get; set; }
+
+ [NotNull]
+ [Required]
+ public HashSet<UpdateLanguageWebModel> Languages { get; set; }
+
+ [NotNull]
+ [Required]
+ public HashSet<UpdateTechnologyWebModel> Technologies { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/User/UserWebModel.cs b/src/DevHive.Web/Models/Identity/User/UserWebModel.cs
new file mode 100644
index 0000000..7ab8cca
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/User/UserWebModel.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using DevHive.Common.Models.Misc;
+using DevHive.Web.Models.Identity.Role;
+using DevHive.Web.Models.Language;
+using DevHive.Web.Models.Technology;
+
+namespace DevHive.Web.Models.Identity.User
+{
+ public class UserWebModel : BaseUserWebModel
+ {
+ public string ProfilePictureURL { get; set; }
+
+ [NotNull]
+ [Required]
+ public HashSet<RoleWebModel> Roles { get; set; } = new();
+
+ [NotNull]
+ [Required]
+ public HashSet<UsernameWebModel> Friends { get; set; } = new();
+
+ [NotNull]
+ [Required]
+ public HashSet<LanguageWebModel> Languages { get; set; } = new();
+
+ [NotNull]
+ [Required]
+ public HashSet<TechnologyWebModel> Technologies { get; set; } = new();
+
+ public List<IdModel> Posts { get; set; } = new();
+ }
+}
diff --git a/src/DevHive.Web/Models/Identity/User/UsernameWebModel.cs b/src/DevHive.Web/Models/Identity/User/UsernameWebModel.cs
new file mode 100644
index 0000000..c533bba
--- /dev/null
+++ b/src/DevHive.Web/Models/Identity/User/UsernameWebModel.cs
@@ -0,0 +1,15 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using DevHive.Web.Attributes;
+
+namespace DevHive.Web.Models.Identity.User
+{
+ public class UsernameWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string UserName { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Language/CreateLanguageWebModel.cs b/src/DevHive.Web/Models/Language/CreateLanguageWebModel.cs
new file mode 100644
index 0000000..a739e7f
--- /dev/null
+++ b/src/DevHive.Web/Models/Language/CreateLanguageWebModel.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Language
+{
+ public class CreateLanguageWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string Name { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Language/LanguageWebModel.cs b/src/DevHive.Web/Models/Language/LanguageWebModel.cs
new file mode 100644
index 0000000..7515e70
--- /dev/null
+++ b/src/DevHive.Web/Models/Language/LanguageWebModel.cs
@@ -0,0 +1,13 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Language
+{
+ public class LanguageWebModel
+ {
+ [NotNull]
+ [Required]
+ public Guid Id { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Language/ReadLanguageWebModel.cs b/src/DevHive.Web/Models/Language/ReadLanguageWebModel.cs
new file mode 100644
index 0000000..3d9d5b6
--- /dev/null
+++ b/src/DevHive.Web/Models/Language/ReadLanguageWebModel.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace DevHive.Web.Models.Language
+{
+ public class ReadLanguageWebModel
+ {
+ public Guid Id { get; set; }
+
+ public string Name { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Language/UpdateLanguageWebModel.cs b/src/DevHive.Web/Models/Language/UpdateLanguageWebModel.cs
new file mode 100644
index 0000000..128d534
--- /dev/null
+++ b/src/DevHive.Web/Models/Language/UpdateLanguageWebModel.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Language
+{
+ public class UpdateLanguageWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string Name { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Post/CreatePostWebModel.cs b/src/DevHive.Web/Models/Post/CreatePostWebModel.cs
new file mode 100644
index 0000000..237259d
--- /dev/null
+++ b/src/DevHive.Web/Models/Post/CreatePostWebModel.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.AspNetCore.Http;
+
+namespace DevHive.Web.Models.Post
+{
+ public class CreatePostWebModel
+ {
+ [NotNull]
+ [Required]
+ public string Message { get; set; }
+
+ public List<IFormFile> Files { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Post/Rating/RatePostWebModel.cs b/src/DevHive.Web/Models/Post/Rating/RatePostWebModel.cs
new file mode 100644
index 0000000..5f0e58f
--- /dev/null
+++ b/src/DevHive.Web/Models/Post/Rating/RatePostWebModel.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace DevHive.Web.Models.Post.Rating
+{
+ public class RatePostWebModel
+ {
+ public Guid PostId { get; set; }
+
+ public bool Liked { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Post/Rating/ReadPostRatingWebModel.cs b/src/DevHive.Web/Models/Post/Rating/ReadPostRatingWebModel.cs
new file mode 100644
index 0000000..a551fb8
--- /dev/null
+++ b/src/DevHive.Web/Models/Post/Rating/ReadPostRatingWebModel.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace DevHive.Web.Models.Post.Rating
+{
+ public class ReadPostRatingWebModel
+ {
+ public Guid Id { get; set; }
+
+ public Guid PostId { get; set; }
+
+ public int Likes { get; set; }
+
+ public int Dislikes { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Post/ReadPostWebModel.cs b/src/DevHive.Web/Models/Post/ReadPostWebModel.cs
new file mode 100644
index 0000000..8238f47
--- /dev/null
+++ b/src/DevHive.Web/Models/Post/ReadPostWebModel.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using DevHive.Common.Models.Misc;
+
+namespace DevHive.Web.Models.Post
+{
+ public class ReadPostWebModel
+ {
+ public Guid PostId { get; set; }
+
+ public string CreatorFirstName { get; set; }
+
+ public string CreatorLastName { get; set; }
+
+ public string CreatorUsername { get; set; }
+
+ public string Message { get; set; }
+
+ public DateTime TimeCreated { get; set; }
+
+ public List<IdModel> Comments { get; set; }
+
+ public List<string> FileUrls { get; set; }
+ // public List<FileContentResult> Files { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Post/UpdatePostWebModel.cs b/src/DevHive.Web/Models/Post/UpdatePostWebModel.cs
new file mode 100644
index 0000000..a0c9b61
--- /dev/null
+++ b/src/DevHive.Web/Models/Post/UpdatePostWebModel.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.AspNetCore.Http;
+
+namespace DevHive.Web.Models.Post
+{
+ public class UpdatePostWebModel
+ {
+ [Required]
+ [NotNull]
+ public Guid PostId { get; set; }
+
+ [NotNull]
+ [Required]
+ public string NewMessage { get; set; }
+
+ public List<IFormFile> Files { get; set; } = new();
+ }
+}
diff --git a/src/DevHive.Web/Models/Technology/CreateTechnologyWebModel.cs b/src/DevHive.Web/Models/Technology/CreateTechnologyWebModel.cs
new file mode 100644
index 0000000..ec9ec15
--- /dev/null
+++ b/src/DevHive.Web/Models/Technology/CreateTechnologyWebModel.cs
@@ -0,0 +1,14 @@
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Technology
+{
+ public class CreateTechnologyWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string Name { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Technology/ReadTechnologyWebModel.cs b/src/DevHive.Web/Models/Technology/ReadTechnologyWebModel.cs
new file mode 100644
index 0000000..94542d7
--- /dev/null
+++ b/src/DevHive.Web/Models/Technology/ReadTechnologyWebModel.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace DevHive.Web.Models.Technology
+{
+ public class ReadTechnologyWebModel
+ {
+ public Guid Id { get; set; }
+
+ public string Name { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Technology/TechnologyWebModel.cs b/src/DevHive.Web/Models/Technology/TechnologyWebModel.cs
new file mode 100644
index 0000000..6e8273b
--- /dev/null
+++ b/src/DevHive.Web/Models/Technology/TechnologyWebModel.cs
@@ -0,0 +1,13 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Technology
+{
+ public class TechnologyWebModel
+ {
+ [NotNull]
+ [Required]
+ public Guid Id { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Models/Technology/UpdateTechnologyWebModel.cs b/src/DevHive.Web/Models/Technology/UpdateTechnologyWebModel.cs
new file mode 100644
index 0000000..3e9fe2a
--- /dev/null
+++ b/src/DevHive.Web/Models/Technology/UpdateTechnologyWebModel.cs
@@ -0,0 +1,15 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+
+namespace DevHive.Web.Models.Technology
+{
+ public class UpdateTechnologyWebModel
+ {
+ [NotNull]
+ [Required]
+ [MinLength(3)]
+ [MaxLength(50)]
+ public string Name { get; set; }
+ }
+}
diff --git a/src/DevHive.Web/Program.cs b/src/DevHive.Web/Program.cs
index 3967a71..6982da9 100644
--- a/src/DevHive.Web/Program.cs
+++ b/src/DevHive.Web/Program.cs
@@ -1,26 +1,23 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
namespace DevHive.Web
{
- public class Program
- {
- public static void Main(string[] args)
- {
- CreateHostBuilder(args).Build().Run();
- }
+ public class Program
+ {
+ private const int HTTP_PORT = 5000;
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.UseStartup<Startup>();
- });
- }
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.ConfigureKestrel(opt => opt.ListenLocalhost(HTTP_PORT));
+ webBuilder.UseStartup<Startup>();
+ });
+ }
}
diff --git a/src/DevHive.Web/Properties/launchSettings.json b/src/DevHive.Web/Properties/launchSettings.json
index 44d86fc..2b65d0b 100644
--- a/src/DevHive.Web/Properties/launchSettings.json
+++ b/src/DevHive.Web/Properties/launchSettings.json
@@ -1,31 +1,36 @@
-{
- "$schema": "http://json.schemastore.org/launchsettings.json",
- "iisSettings": {
- "windowsAuthentication": false,
- "anonymousAuthentication": true,
- "iisExpress": {
- "applicationUrl": "http://localhost:1955",
- "sslPort": 44326
- }
- },
- "profiles": {
- "IIS Express": {
- "commandName": "IISExpress",
- "launchBrowser": true,
- "launchUrl": "swagger",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- },
- "DevHive.Web": {
- "commandName": "Project",
- "dotnetRunMessages": "true",
- "launchBrowser": true,
- "launchUrl": "swagger",
- "applicationUrl": "http://localhost:5000",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- }
- }
- }
-}
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:1955",
+ "sslPort": 44326
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": false,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "DevHive.Web": {
+ "commandName": "Project",
+ "dotnetRunMessages": "true",
+ "launchBrowser": false,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "DevHive.Web Production": {
+ "commandName": "Project",
+ "dotnetRunMessages": "true",
+ "launchBrowser": false,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Production"
+ }
+ }
+ }
+}
diff --git a/src/DevHive.Web/Startup.cs b/src/DevHive.Web/Startup.cs
index 303c080..46521cf 100644
--- a/src/DevHive.Web/Startup.cs
+++ b/src/DevHive.Web/Startup.cs
@@ -1,59 +1,70 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.HttpsPolicy;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Microsoft.OpenApi.Models;
-
-namespace DevHive.Web
-{
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- 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.AddControllers();
- services.AddSwaggerGen(c =>
- {
- c.SwaggerDoc("v1", new OpenApiInfo { Title = "DevHive.Web", Version = "v1" });
- });
- }
-
- // 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.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- app.UseSwagger();
- app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "DevHive.Web v1"));
- }
-
- app.UseHttpsRedirection();
-
- app.UseRouting();
-
- app.UseAuthorization();
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- });
- }
- }
-}
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using DevHive.Web.Configurations.Extensions;
+using Newtonsoft.Json;
+
+namespace DevHive.Web
+{
+ public class Startup
+ {
+ public Startup(IConfiguration configuration)
+ {
+ Configuration = configuration;
+ }
+
+ 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.AddCors();
+
+ services.AddControllers()
+ .AddNewtonsoftJson(x =>
+ {
+ x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+ });
+
+ services.DatabaseConfiguration(Configuration);
+ services.SwaggerConfiguration();
+ services.JWTConfiguration(Configuration);
+ services.AutoMapperConfiguration();
+ services.DependencyInjectionConfiguration(this.Configuration);
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ app.UseCors(x => x
+ .AllowAnyMethod()
+ .AllowAnyHeader()
+ .SetIsOriginAllowed(origin => true) // allow any origin
+ .AllowCredentials()); // allow credentials
+
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ app.UseSwaggerConfiguration();
+ }
+ else
+ {
+ app.UseHsts();
+ app.UseExceptionHandlerMiddlewareConfiguration();
+ }
+
+ app.UseDatabaseConfiguration();
+ app.UseAutoMapperConfiguration();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllerRoute(
+ name: "default",
+ pattern: "api/{controller}/{action}"
+ );
+ });
+ }
+ }
+}
diff --git a/src/DevHive.Web/appsettings.json b/src/DevHive.Web/appsettings.json
index 81ff877..bcdcae7 100644
--- a/src/DevHive.Web/appsettings.json
+++ b/src/DevHive.Web/appsettings.json
@@ -1,10 +1,20 @@
-{
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft": "Warning",
- "Microsoft.Hosting.Lifetime": "Information"
- }
- },
- "AllowedHosts": "*"
-}
+{
+ "AppSettings": {
+ "Secret": "gXfQlU6qpDleFWyimscjYcT3tgFsQg3yoFjcvSLxG56n1Vu2yptdIUq254wlJWjm"
+ },
+ "ConnectionStrings": {
+ "DEV": "Server=localhost;Port=5432;Database=API;User Id=postgres;Password=;"
+ },
+ "Cloud": {
+ "cloudName": "devhive",
+ "apiKey": "488664116365813",
+ "apiSecret": ""
+ },
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}