Saturday, October 31, 2020

What are some skills possessed by software engineers at big companies like Google, Samsung, Amazon Facebook etc that software engineers at no-name companies usually don’t have?


This blog is not technical and I was having a fever so can't open a laptop but thanks to the phone they also do their work wisely.

I have worked and interviewed several times with this big, small, mid damn every size of companies and there is a difference and it is a very thin line. Let me explain.

I am working in software engineering for the last 10 years. I come from a no-name college in India, and my grades weren’t stellar. SO, getting into top tier companies was hard for me. Over 10 years, I’ve worked my way up, and I was in Samsung , IndiGo and after that got opportunity to work for (Amazon, Google) Big Companies etc.

 On the way, I have worked in all kinds of companies: startups, mid sized companies, large multi nationals; and in all kinds of industries: consumer goods, healthcare, finance, education

First of all, Companies are tiered in terms of the skill levels of their engineers. They pretend not to be. Everyone claims that they hire the smartest engineers. WHat they mean is that they hire the smartest engineers that they can get. There is a definite differrence in Engineers working in FAANG companies (Facebook, Amazon, Apple, Netflix, Google), I’ve seen all kinds of engineers beleive me and I was the only one worked in between the IIT'ns with respect.

Here’s the kicker. The biggest difference isn’t in the quality of the code that they write. FAANG engineers, on the whole, write as buggy code as engineers in decent companies.

The biggest differentiator is Communication. When I was in mid-tier companies, I was constantly finding myself explaining and re-explaining things in great detail. In fact, I would say that at most companies at mid-tier level, your success as an engineer depends on being able to drive people in the right direction by communicating to them.

There are 3 kind of people in tech. 

There are

 a) arguers:- people who will fight every point of view that isn’t their own, 

b) receivers: people who will try their best to understand what you are saying

 c) analyzers: people who start thinking critically while you are talking to them.

 Arguers are toxic. Receivers are good but slow. Analyzers are good and fast.

In mid tier companies, you are more likely to find Arguers and Receivers, whereas in top-tier companies, you are more likely to find Receivers and Analyzers.

To be a successful tech company, you need to get in as many Analyzers as you can. Because these are the people who generate ideas. These are the people you give 2 and 2 and they figure out how to make 8. Not only that, with ANalyzers, you have to spend less time getting the team on the same page. 

Less miscommunication = Less rework = shorter turnaround = lower time to market = win.

Just to be clear, I’m not saying communication is bad. Communication is good. You need to make sure everyone understands what needs to be done. Communication is essential. All I’m saying is that in top tier companies, communication is lot more efficient.

And that is the biggest difference. I have seen and also was a part of it as a analyzer.

Sunday, October 18, 2020

Analysis of Algorithm - Java

 

I was getting comments on it to explain the concept. I have tried to capture my concept on paper but it could have better on video and will upload the video ASAP.

Analysis of the algorithm:

In this article, I will try to give you brief in the easiest way possible and also write 3 functions/methods that return the sum of first n natural numbers and using these functions I will explain the concept of it. It is very basic but very important to understand others you will be confused like what is the difference between Big O of N and Theta of  N. Most people fail to explain it. here I will stick to my topic and will try not to go beyond.

and analyze these different functions in detail and compare them with each other on the basis of the time taken by them individually.

Let's understand the analysis with this example.

Given a number n, write a function/method to find the sum of first n natural numbers. very simple right?

I/P= n= 3

O/P = 6

I/P= n= 5

O/P = 15

So it is like if n =3 then 1+2+3 = 5 sum of first natural numbers right?

And if n =5 then it is like 1+2+3+4+5 =15

So now I am gone a write 3 different solutions for this program and try to analyze it.

Soution 1 :

int fun(int n)

{

  return n*(n+1)/2 ;

}

What it does?:

it simply uses the formula of first n natural numbers So like the first 3 natural numbers you will do like 3*(3+1)/2 = 6

Solution 2:

int fun2(int n)

{

  int sum = 0;

  for(int i=0;i<=n ; i++)

  {

    sum = sum + i ;

  }

  return sum;

}

What it does?

is like simply runs a loop to sum numbers from 1 to n. 

Solution 3:

int fun3(int n)

{

  int sum =0;

  for(int  i=1 ; i<=n ; i++)

      for(int j=1 ; j<=i; j++)

  sum ++;

 return sum;   

}

what it does?

it goes from i to 1 to n and for every i it increments the sum by i times.

1 + (1+1) + (1+1+1) for n =3 

Now how would you decide which one is better among all these functions?

The analysis which handles all these 3 functions is called Asymptotic analysis and basically, we measure the order of growth of a program or an algorithm in terms of input size.

So here I am writing an expression for the time taken by these 3 different functions

fun1() - > c1

fun2() - > c2n + c3

fun3() - > c4n^2 + c5n + c6

where c1,c2,c5,c6 all are constants 

n = input size for the program.

Now I am going to tell you how to get these expressions. So the first function does the constant work however how? like if you pass n = 10000 then also it will compute like

10000*(10000 + 1)/2 right? and even if you pass 100 it will do the same way right? So no matter what you pass as input size the number of operations you are doing is constant and it is not dependent upon the value of its input size And what operations you are doing So what are the operations here you are doing is like one initiation, one multiplication, and one division right?

these 3 operations are not dependent upon anything it will be the same for 10, 100, 1000, 1000000, etc right? and that is why I have written constant C1 on the above expression for that function .

Now let see function2 and think why we do get c2n + c3 SO in this function we do some constant amount of work here like 

int fun2(int n)

{

  int sum = 0;                  // 1) this is a constant work right?

  for(int i=0;i<=n ; i++)       //2) the initialization of i is also constant work

  {

    sum = sum + i ;             // 3)Similarly it is also a constant work 

  }

  return sum;

}

So why I am always saying constant work because it will always happen exactly once whether you pass n = 10, n= 1000, n =1000000000, etc. it will not depend on input size right? but there is some work which depends upon the input size n. 

sum = sum + i  // this will execute the 100 times if n=100 and ten thousands time if n = 10,000 right?

 Similarly this for(int i=0;i<=n ; i++) // this i++ will  also depend upon the input size of the n . it will also increment based on the input size right?

 Similarly, the condition checks i<=n will also depend on the input size right?

 So there is some work which happens constant times So if I write it C2 time and the rest of the work is constant time So we can write  it as C2n + C3

Now analyze the function 3 what happens in this case is 

int fun3(int n)

 {

  int sum =0;

  for(int  i=1 ; i<=n ; i++)

      for(int j=1 ; j<=i; j++)

  sum ++;    

  return sum;   

 }

this sum ++ is going to happen how many times? It will happen n * (n+1)/2 times right? If you notice the program the inner loop will run for  i=1 for 1 time and i=2 for 2 times and so on right? So it is going to run 1 + (1+1) + (1+ 1+ 1) So ultimately you have an expression which runs 

 n *(n + 1)/2 and you have more expression like you constant works also right So we can write it as 

 n*(n+1)/2 + Constant

 So now whenever you think of analysis of algorithm always think of the size of input which is larger than or equal to zero because your input size can never be negative.

 And also the time taken by the function be should greater than or equal to zero because your algorithm or program can never take a negative time.

 So now see the static analysis all those above programs may work faster for small input size may be the function 2 or function 3 works faster for the small input size but when you increment the input size like 10000000 than you will notice actually the function 2 and function 3 is taking more than function 1.So one more thing the function 1 will always give you the linear time taken to execute the program as it does not depend on the input size like I explained above.

 There are mathematical ways of analysis also for comparing which algorithms are better and we measure it in terms of the order of growth.

So this is how you compare which algorithm is better and which is not? keep in mind that it also depends upon the programming language and the machine that you use to compare the algorithms.

And one more point the Big O of N gives you the probable complexity whereas Theta of N will give you the exact complexity and information of the algorithm.I can discuss more on this but in the next blog will tell what is the difference when I say Big O of N and Theta of N of an Algorithm.

 

 

 






























Saturday, September 19, 2020

Microservice Spring Java Interview Question - Is it the best approach to implement the REST for inter-microservices communication? or any other alternatives

Question :

Are there other alternatives for inter-microservices communication? Is it the best approach to implement the REST for inter-microservices communication?

Ans:

the microservices we have developed are based on REST. We have used REST for both internal (inter-microservice, where one microservice communicates with another microservice in the same system) and external (through the public API) communication. At present, REST fits best for the public API. 

You can build microservices that are purely asynchronous. You can build microservice-based systems that would communicate based on events. There is a tradeoff between REST and event-based microservices. 

REST provides synchronous communication, whereas reactive microservices are based on asynchronous communication (asynchronous message passing). We can use asynchronous communication for inter-microservice communication. Based on the requirement and functionality, we can choose REST or asynchronous message passing.

 Consider the example case of a user placing an order, which makes a very good case for implementing reactive microservices. On successful order placement, the inventory service would recalculate the available items; the account service would maintain the transaction, correspondence service would send the messages (SMS, emails, and so on) to all involved users such as a customer and a supplier. 

In this case, more than one microservice may perform distinct operations (inventory, accounts, messaging, and so on) based on an operation (order placement) performed in one microservice. Now, just think if all these communications were synchronous. Instead, reactive communication, with asynchronous message passing, provides efficient use of hardware resources, non-blocking, low latency, and high throughput operations. 

We can primarily divide the microservice implementations into two groups—REST-based microservices and event-based/message-driven microservices. Reactive microservices are event-based.

So now what is reactive microservice?

A reactive microservice is based on the reactive manifesto and it has four principles.

for reference please go through it

https://www.reactivemanifesto.org/




1)Responsive
2)Resilient
3)Elastic
4)Message Driven

Reactive microservice performs operations in response to events like a single event, a microservice can have multiple producers or consumer events. Also, a microservice can have both producer and consumer events. like in the Booking microservice that creates the new booking (POST /v1/booking). This will be our event source and would make use of Apache Kafka for sending this event. Other microservices can consume this event by listening to the event. On a successful booking call, the Booking microservice will produce the event bookingOrdered.

So that why we should be focusing on the Reactive Microservice Architecture.



 

Friday, August 14, 2020

Microservices build pipeline (Peeling Concept) - Java Example

 Microservices could be built and tested using CI/CD tools such as Jenkins, TeamCity, and so on. In microservices, each microservice is like a small application.

For example, once you commit the code in the repository(SCM), CI/CD tools trigger the build process:

- Cleaning Code

- Code Compilation

- Unit Test Execution

- Contract/Acceptance Test Execution

- Building the application container images/archives

- Publishing the archives

- Deployment in various environments such as Dev, QA, STAGE, and PROD, etc.

- Integration and Functional test execution

So after this release-build triggers that change the SNAPSHOT version in pom.xml build the artifacts. Publish the artifacts to the repository. Tag this version in the repository.If you are using the container image then build the container image as a part of the build.

Deployment using Docker

Previously, VMs(Virtual Machines) were used to create software images that could be deployed wherever needed. As of now, Container such as Docker becomes very popular as it is compatible with old vs new(cloud) build environments.

Containers

So containers provide a lightweight runtime environment that consists of the core features of VMs and isolated service of operating systems. So a container basically runs as an application(microservice) within the OS. The OS is basically on top of the hardware and each OS could have multiple containers, with a container running the application.

A container uses kernel interfaces such as cnames and namespaces that allow multiple containers to share the same kernel while running in complete isolation to one another.





Docker

Docker is open-source and it makes use of the Linux Kernel features such as groups and namespaces because to ensure resource isolation and packaging of the application you can with its dependencies.

you can also run as expected across different Linux OS/distributions.SO you can develop an application in any language and then easily deploy it.

Containers are made of just the application and its dependencies including the basic OS. In docker container, everything executes natively on the host and uses the host kernel directly.That's why each container has its own user namespace.

Docker uses a client-server architecture. the docker client is a user interface that is used by an end-user and it communicates back and forth with a Docker daemon. Docker daemon actually does the building, running, and distributing of your docker containers.at the same time docker client and docker daemon can run on the same system or different machines.

The Docker client and daemon communicate via sockets or through a RESTful API.

Docker Architecture

Main components of Docker :

1)Docker Image: This is basically a read-only template like an image that could contain an Ubuntu OS with an apache web server and your web application installed. So it is a build component of Docker and images are used to create docker containers.

2)Docker container: A docker container is created from a Docker image. The docker container can only see its own process and its own filesystem layered onto a host filesystem and a networking stack that pipes to the host-networking stack. Docker containers can be run started stopped moved or deleted.


Microservices deployment with docker deals with 3 parts:

- Application packaging like JAR

- Building Docker Image with a JAR and dependencies using a Docker instruction file, the Dockerfile and command docker build. 

- Docker container execution from this newly build image using command docker run.

So ultimately Containerization is an efficient way to simplify microservices deployment.


The detail concept will cover in the next blog. Thanks.

Monday, May 25, 2020

Design Pattern - Design and Implement Snake and Ladders Game

Design and Implement Snake and Ladders Game 

I will write the code and tell you the thought process of how one should proceed in Design and implement the code. Snake and Ladder show how various objects like a game board, snack, ladders, etc come together to produce a program. Snack and ladder game is a very famous interview question to check your design pattern concept. I think we all know about the Snack and Ladder Game how we play it So I will jump to design pattern.

In the Snake and Ladder game, there are some objects that will need to be created like below:
  • GameBoard
  • PlayerPiece
  • BoardSquare
  • Snake
  • Ladder
  • Die
And one more thing we need an object of the game itself. the main design decisions we have to take based on their responsibilities of Objects.

So Die should be rolled this is the Die object responsibility. What about BoardSquare or even the Game itself? So we could keep track of which piece is on which square using the BoardSquare or even the game itself. What about PlayerPiece?It should have a useful role in the application like it will be responsible for knowing which BoardSquare it currently occupies. There is an association between PlayerPiece and BoardSquare.

This is just one way of designing the solution. Just give a thought about the Snake and Ladder classes?
Why because they are very similar in fact could be modeled as a single class that links two squares together whether they take the player up or down on the board does not really make any difference to the implementation but we will keep them apart.

What do we do about the relationship between the Snack and ladders and the BoardSquares?
A BoardSquare needs to know if it contains the head of a snake or the foot of ladder though it does not need to know if it has the tail of a snake or the head of a ladder because these do not cause the PlyerPiece to move again. We cannot have both a snake and a ladder on any one square.

The main logic:

Finally, the SnakeAndLadders class acts as the program entry point and creates the GameBoard and the PlyerPieces. it has the main method that creates an instance of the class and triggers the play method. This handles the main game loop that iterates until the game is over.

Implementation :

So the Snake and Ladder objects need to be positioned on the board so they can be referenced by the BoardSquare that they are placed on and reference the other BoardSquare that they point to. Now to set a position of a Snake, a parameterized constructor is provided that takes the head of and tail positions as parameters.


Snake(BoardSquare head, BoardSquare tail){
 setTail(tail);
head.addSnake(this);
}

Similarly the Ladder constructor stores the top of the ladder and passes itself back to the BoardSquare that contains its foot.

Ladder(BoardSquare top, BoardSquare foot)
{
   setTop(top);
   foot.addLadder(this)
}

in both the case we omit the public prefix because the class itself is not public.

class Snake
{
  private BoardSquare tail;
  Snake(BoardSquare head,BoardSquare tail)  
  {
    setTail(top);
head.addSnake(this);
  }
  private void setTail(BoardSquare tail)
  {
    this.tail=tail;
  }
  private BoardSquare getTail()
  {
    return tail;
  }
  
  void movePlayerPiece(PlayerPiece counter)
  {
    System.out.println("Down the Snake to " + getTail().getPosition());
counter.setCurrentPostion(getTail());
  }
}

class Ladder
{
  private BoardSquare top;
  Ladder(BoardSquare top,BoardSquare foot)  
  {
    setTail(top);
head.addLadder(this);
  }
  private void setTop(BoardSquare top)
  {
    this.top=top;
  }
  private BoardSquare getTop()
  {
    return top;
  }
  void movePlayerPiece(PlayerPiece counter)
  {
    System.out.println("Up the Ladder to " + getTop().getPosition());
counter.setCurrentPostion(getTop());
  }
}

class PlayerPiece
{
 private BoardSquare currentPosition; 
 private String color;
 PlayerPiece(String color)
 {
   setColor(color);
 }
  private void setColor(String color)
  {
    this.color=color;
  }
  String getColor()()
  {
    return color;
  }
  BoardSquare getCurrentPosition()
  {
    return currentPosition;
  }
  void setCurrentPostion(BoardSquare newPosition)
  {
   currentPosition = newPosition
  }
}

class BoardSquare
{
 private Snake aSnake = null;
 private Ladder aLadder = null;
 private int position;
 BoardSquare(int position)
 {
   setPosition(position);
 }
 int getPosition()
 {
   return position;
 }
 private void setPosition(int position)
 {
  this.position = position;
 }
 void addSnake(Snake s)
 {
   aSnake = s
 }
 public void addLadder(Ladder l)
 {
  aLadder = l;
 }
 private boolean hasSnake()
 {
  return null!=aSnake;
 }
 private boolean hasLadder()
 {
   return null!=aLadder;
 }
 
 public void movePlayerPiece(PlayerPiece counter)
  {
counter.setCurrentPostion(this);
if(hasSnake())
{
  aSnake.movePlayerPiece(counter);
}
if(hasLadder())
{
  aLadder.movePlayerPiece(counter);
}
  }
}



private BoardSquare[] squares;
private Die die;
static final int MAX_SQUARES = 100;
class Gameboard
{
  static final int START_SQUARE =1;
  Gameboard()
  {
    die = new Die();
squares = new BoardSquare[START_SQUARE + MAX_SQUARES];
for(int i=START_SQUARE;i<=MAX_SQUARES;i++)
{
  squares[i]=new BoardSquare[i];
}
  }
  
  // add the Ladders
  new Ladder(squares[38],squares[1]);
  new Ladder(squares[14],squares[4]);
  new Ladder(squares[31],squares[9]);
  new Ladder(squares[42],squares[21]);
  new Ladder(squares[84],squares[28]);
  new Ladder(squares[44],squares[36]);
  new Ladder(squares[67],squares[51]);
  new Ladder(squares[91],squares[71]);
  new Ladder(squares[100],squares[80]);
  
  //add the Snakes
  
  new Snake(squares[16],squares[6]);
  new Snake(squares[47],squares[26]);
  new Snake(squares[49],squares[11]);
  new Snake(squares[56],squares[53]);
  new Snake(squares[62],squares[19]);
  new Snake(squares[64],squares[60]);
  new Snake(squares[87],squares[24]);
  new Snake(squares[93],squares[73]);
  new Snake(squares[95],squares[75]);
  new Snake(squares[98],squares[78]);
  
  // constructor creates the square and adds the 
  
  BoardSquare getStartSquare()
  {
    return square[START_SQUARE];
  }
  
  public void movePlayerPiece(PlayerPiece counter)
  {
BoardSquare current = counter.getCurrentPosition();
int nextPosition = current.getPosition() + die.getRoll();
if(nextPosition > MAX_SQUARES)
{
  System.out.println("you need to land  exactly on the last suquare to win!");
}
else
{
  counter.moveTo(squares[nextPosition]);
}
System.out.println(counter.getColor + "counter on " + counter.getCurrentPosition().getPosition());
  }
}

public class SnakesAndladders
{
  private Gameboard board;
  public SnakesAndladders()
  {
    board = new Gameboard();
  }
  public void play()
  {
    PlayerPiece counter = new PlayerPiece("RED")
counter.setCurrentPostion(board.getStartSquare());
while(counter.getCurrentPosition(),getPosition() < Gameboard.MAX_SQUARES)
{
  board.movePlayerPiece(counter)
}
System.out.println(counter.getColor + "counter finished on  " + counter.getCurrentPosition().getPosition());
  }
  public static void main(String[] args)
  {
     SnakesAndladders myGame = new SnakesAndladders();
myGame.play()
  }
}


Output : 

up the ladder tp 14
RED counter on 14
RED counter on 15
...........................
.............................
.............................
RED counter on 100
RED counter finished on 100








Peeling Concept of Dynamic Programming , Data-Structures and Algorithm

Peeling Concept of Dynamic Programming Data-Structures and Algorithm

Dynamic Programming(DP): Dp is a very simple technique but at the same time very difficult to master. The problem is how to identify and solve DP problems.

Another thing just keep in mind that DP and memorization(Means maintaining a table of subproblems already solved) work together. So what is the main difference between the 
Divide and Conquer and DP? Divide-Conquer,subproblems are independent whereas in DP the overlap of subproblems occur. This is the main difference.

So now why memoization? because it reduces the exponential complexity to polynomial complexity O(n2), O(n3) for many subproblems.

The major components of DP :

a)Recursion: Solves subproblems recursively.
b)Memorization: Stores already computed values in the table

Dynamic Programming = Recursion + Memorization

So how to identify that this problem will be solved by DP. Keep in mind.
a)Optimal substructure - So an optimal solution to a problem contains the given subproblems.
b)Overlapping subproblems- a recursive solution of subproblems.

So another question can we solve every problem using Dynamic programming?
The answer is no like greedy and divide and conquer not able to solve everything it is that same way. You have to understand one thing the difference between the DP and straightforward recursion is in the memorization of recursive calls.

If subproblems are independent and there is no repetition then memorization does not help so DP is not a solution to such problems.

Dynamic Programming Approaches

to solve any DP problem we have two approaches

1)Bottom-up dynamic programming
2)Top-down dynamic programming


Bottom-up Dynamic Programming : 

So here we start with smallest possible input argument value and then slowly increase input argument value and while doing this we store values in a table(memory).

Top-down Dynamic Programming:

So here we broke the problem in subproblems and these subproblems are solved and the solutions remembered in case they need to be solved. Also we save each computed value as a final action of a recursive function and at the same, we also check if pre-computed values exist.

Algorithms of Dynamic Programming : 

These are a few algorithms of DP.

1)String Algorithms include the longest common subsequence, longest increasing subsequence, longest common substring, edit distance.

2)Bellman-Ford Algorithm, Floyd's All pair shortest path algorithm.

3)Chain Matrix multiplication

4)Subset Sum

5)0/1 Knapsack

6)Travelling salesman problem 

Let's understand the Dynamic Programming in more depth:

Fibonacci Series(Current number is the sum of two previous number).Remember it.

Fib(n) = 0      for n =0
Fib(1) = 1      for n=1
           =  Fib(n-1) + Fib(n-2) ........ for n  > 1

So now think of its recursive solution which is very simple.

int RecursiveFibonacci(int n)
{
   if(n==0) return 0;
   if(n==1) return 1;

   return RecursiveFibonacci(n-1) + RecursiveFibonacci(n-2);
}

Above we discuss about Memorization So how Memorization helps here?
Ans: It helps like it produces a call tree that calls the function on the same value many times.

Fib(5) 
Fib(4) + Fib(3)
(Fib(3) + Fib(2))  + (Fib(2) + Fib(1))
...............

(((Fib(1) + Fib(0)) + Fib(1)) + (Fib(1) + Fib(0) + Fib(0))) + Fib(0) + Fib(1))

So here Fib(2) was calculated 3 times(overlapping of subproblems) this leads to an exponential time. Instead of solving the same subproblems again and again just keep track of it store the previously calculated values then it reduces the complexity. 

Bottom-up Approach:

int fib[n];
int fib(int n)
{
   if(n==0 || n==1)
   retun 1
   
   fib[0] =1;
   fib[1] =1;
   for(int i =2 ; i<n; i++)
   {
     fib[i] = fib[i -1] + fib[i-2]
   }
   
   return fib[n -1]
}

Top-down Approach :

int fib[n];
int fibonacci(int n)
{
   if(n==1) retun 1;
   if(n==2) retun 1;
   if(fib[n]!=0)
    {
  return fib[n];
}  
   return fib[n] = fibonacci(n -1) + fibonacci(n -2);
}

So both of them reduces the problem of complexity to O(n) this is because if a value is already computed then we are not calling the subproblems again. We are directly taking it from
table.

Time Complexity O(n) 
Space Complexity: O(n) for table.

We can further improve the space complexity by O(1)

So the question is How?
Ans: So just think about Fibonacci series is basically the current value is the sum of two previous calculations only. So we do not have to store all the previous values right? we just have two store last two values we can calculate the current value. 


















Sunday, May 24, 2020

Send Email in Python Example

Email Send in Python :

So for this first, you have to install the flask-mail library. make sure you are in the same virtual environment.use the following command to install the same.

(venv)$ pip install Flask-Mail

Once installed you have to initiate and configure flask mail.


Code :

cuurent_appp.config - this is just a configuration.

MAIL_DEFAULT_SENDER = 'your_email_address'
MAIL_SERVER = 'email_providers_smtp_address'
MAIL_PORT='mail_server_port'
MAIL_USERNAME='your username'
MAIL_PASSWORD='your password'
MAIL_USE_TLS=False
MAIL_USE_SSL=True


from flask_mail import Message,Mail
mail = Mail()

 for the initiate, it just calls below
 
mail.init(app) 

def send_email(to,subject,template):
    msg = Message(
       subject,
   receipts=[to],
   html=template,
   sender=cuurent_app.config['MAIL_DEFAULT_SENDER']
                   )
   mail.send(msg)
 
Use the above code to send the email. Thanks!



Building REST APIs with FLASK Python Web Services- CRUD Application with User Authentication

User Authentication 

So once we have all our routes in place and we need to add in user authentication to ame sure only logged-in users can access certain routes. So now we will add in user login
and signup routes but before we need to add schema.

Create users.py:

In schema add two static methods to encrypt the password and verify password and for the same we will need a python library called "passlib".

just install this library by using the below command.

(venv)$ pip install passlib

Let's write the required code.

from api.database import db
from passlib.hash import pbkdf2_sha256 as sha256
from marshmallow_sqlalchemy import ModelSchema
from marshmallow import fields

class User(db.Model):
     _tablename_ = 'users'
 
  id = db.Column(db.Integer,primary_key=True)
  username = db.Column(db.String(120),unique = True,nullable = False) 
  password= db.Column(db.String(120),nullable=False)
  
   
def create(self):
        db.session.add(self)
db.session.commit()
return self
    @classmethod
def find_by_username(cls,username):
    return cls.query.filter_by(username=username).first()
@staticmethod
    def generate_hash(password):
    return sha256.hash(password)
@staticmethod
    def verify_hash(password,hash):
    return sha256.verify(password,hash)
class UserSchema(ModelSchema):
     class Meta(ModelSchema.Meta):
       model = User
   sqla_session = db.session
id = fields.Number(dump_only=True)    
username = fields.String(required=True)
 
Next create users.py in routes directory and we will add user login and signup routes.

For user authentication across the application we will use JWT(JSON WEB TOKENS) authentication. In a flask, there is an opensource extension called Flask-JWT-Extended which
provides JWT support and other helpful methods.

Now install flask-JWT-Extended by using the following command.
(venv)$ pip install flask-JWT-Extended

@user_routes.route('/',methods=['POST'])
def create_user():
    try: 
    data = request.get_json()
data['password'] = User.generate_hash(data['password'])
user_schema = UserSchema()
user,error = user_schema.load(data)
result = user_schema.dump(user.create()).data
return response_with(resp.SUCCESS_201)
except Eception as e:
        print e
        return response_with(resp.INVALID_INPUT_422)
Now we will add a method for the signed-up users to login.

@user_routes.route('/login',methods=['POST'])
def authenticate_user():
    try: 
    data = request.get_json()
current_user = User.find_by_username(data['username'])
if not current_user:
     return response_with(resp.SERVER_ERROR_404)
 
if User.verify_hash(data['password'],current_user.password):
     access_token = create_access_token(identity=data['user_name'])
return response_with(resp.SUCCESS_201,value={'message':'Logged in as {}.format(current_user.username)'})
else:

             return response_with(resp.UNAUTHORIZED_401)
except Exception as e:
      print e
      return response_with(resp.INVALID_INPUT_422)   
  
The following code will take the username and password as input and verifies it. We have created a successful REST application with user authentication.